Watt-32 tcp/ip  2.2 dev-rel.10
split.c
Go to the documentation of this file.
1 
6 /* Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  * must display the following acknowledgement:
18  * This product includes software developed by Gisle Vanem
19  * Bergen, Norway.
20  *
21  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * G. Vanem <gvanem@yahoo.no> 2002
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #include "wattcp.h"
39 #include "pcsed.h"
40 #include "pcpkt.h"
41 #include "pppoe.h"
42 #include "ppp.h"
43 #include "misc.h"
44 #include "strings.h"
45 #include "bsddbug.h"
46 #include "ip6_in.h"
47 #include "split.h"
48 
49 #if defined(NEED_PKT_SPLIT)
50 
51 #define MARKER 0xDEAFABBA
52 #define MAX_SPLITS 10
53 
54 static struct pkt_split split_list_in [MAX_SPLITS];
55 static struct pkt_split split_list_out[MAX_SPLITS];
56 
57 static void split_mac (struct pkt_split *, const void *);
58 static void split_ip4 (struct pkt_split *, const in_Header *);
59 static void split_ip6 (struct pkt_split *, const in6_Header *);
60 
61 const struct pkt_split *pkt_get_split_in (void)
62 {
63  WATT_ASSERT (*(DWORD*)&split_list_in[MAX_SPLITS-1] == MARKER);
64  return (&split_list_in[0]);
65 }
66 
67 const struct pkt_split *pkt_get_split_out (void)
68 {
69  WATT_ASSERT (*(DWORD*)&split_list_out[MAX_SPLITS-1] == MARKER);
70  return (&split_list_out[0]);
71 }
72 
73 const struct pkt_split *pkt_get_type_in (enum Components type)
74 {
75  const struct pkt_split *ps;
76 
77  for (ps = pkt_get_split_in(); ps->data; ps++)
78  if (type == ps->type)
79  return (ps);
80  return (NULL);
81 }
82 
83 const struct pkt_split *pkt_get_type_out (enum Components type)
84 {
85  const struct pkt_split *ps;
86 
87  for (ps = pkt_get_split_out(); ps->data; ps++)
88  if (type == ps->type)
89  return (ps);
90  return (NULL);
91 }
92 
93 const struct pkt_split *pkt_split_mac_in (const void *ptr)
94 {
95  *(DWORD*) &split_list_in[MAX_SPLITS-1] = MARKER;
96  split_mac (&split_list_in[0], ptr);
97  return (&split_list_in[0]);
98 }
99 
100 const struct pkt_split *pkt_split_mac_out (const void *ptr)
101 {
102  *(DWORD*) &split_list_out[MAX_SPLITS-1] = MARKER;
103  split_mac (&split_list_out[0], ptr);
104  return (&split_list_out[0]);
105 }
106 
107 static void split_mac (struct pkt_split *ps, const void *ptr)
108 {
109  const link_Packet *pkt = (const link_Packet*) ptr;
110  const in_Header *ip = NULL;
111  WORD type = 0;
112 
113  if (_pktserial) /* SLIP/PPP/AX25 doesn't have MAC header */
114  {
115  ip = &pkt->ip.head;
116  if (ip->ver == 6)
117  split_ip6 (ps, (const in6_Header*)ip);
118  else split_ip4 (ps, ip);
119  return;
120  }
121 
122  if (_pktdevclass == PDCLASS_TOKEN)
123  {
124  const tok_Packet *tr = &pkt->tok;
125 
126  ps->type = TYPE_TOKEN_HEAD;
127  ps->data = pkt;
128  ps->len = sizeof(tok_Header);
129 
130  ip = (const in_Header*) &tr->data[0];
131  type = tr->head.type;
132  }
133  else if (_pktdevclass == PDCLASS_FDDI)
134  {
135  const fddi_Packet *fddi = &pkt->fddi;
136 
137  ps->type = TYPE_FDDI_HEAD;
138  ps->data = pkt;
139  ps->len = sizeof(fddi_Header);
140 
141  ip = (const in_Header*) &fddi->data[0];
142  type = fddi->head.type;
143  }
144  else if (_pktdevclass == PDCLASS_ARCNET)
145  {
146  const arcnet_Packet *arc = &pkt->arc;
147 
148  ps->type = TYPE_ARCNET_HEAD;
149  ps->data = pkt;
150  ps->len = ARC_HDRLEN;
151 
152  ip = (const in_Header*) ((BYTE*)arc + ARC_HDRLEN);
153  type = arc->head.type;
154  }
155  else if (_pktdevclass == PDCLASS_ETHER)
156  {
157  ps->type = TYPE_ETHER_HEAD;
158  ps->data = pkt;
159  ps->len = sizeof(eth_Header);
160 
161  ip = (const in_Header*) &pkt->eth.data[0];
162  type = pkt->eth.head.type;
163  }
164 
165  if (type == IP4_TYPE)
166  {
167  ps++;
168  split_ip4 (ps, ip);
169  return;
170  }
171 
172  if (type == IP6_TYPE)
173  {
174  ps++;
175  split_ip6 (ps, (const in6_Header*)ip);
176  return;
177  }
178 
179  if (type == ARP_TYPE)
180  {
181  ps++;
182  ps->type = TYPE_ARP;
183  ps->data = &pkt->eth.data[0];
184  ps->len = sizeof(arp_Header);
185  }
186  else if (type == RARP_TYPE)
187  {
188  ps++;
189  ps->type = TYPE_RARP;
190  ps->data = &pkt->eth.data[0];
191  ps->len = sizeof(rarp_Header);
192  }
193  else if (type == PPPOE_DISC_TYPE)
194  {
195  pppoe_Packet *pppoe = (pppoe_Packet*)&pkt->eth.data[0];
196 
197  ps++;
198  ps->type = TYPE_PPPOE_DISC;
199  ps->data = pppoe;
200  ps->len = intel16 (pppoe->length);
201  }
202  else if (type == PPPOE_SESS_TYPE)
203  {
204  const pppoe_Packet *pppoe = (const pppoe_Packet*)&pkt->eth.data[0];
205  WORD proto = intel16 (*(WORD*)&pppoe->data[0]);
206 
207  ps++;
208  ps->type = TYPE_PPPOE_SESS;
209  ps->data = pppoe;
210  ps->len = PPPOE_HDR_SIZE;
211  if (proto == intel16(PPP_IP))
212  {
213  ip = (const in_Header*)&pppoe->data[2];
214  split_ip4 (++ps, ip);
215  return;
216  }
217  if (proto == PPP_LCP)
218  {
219  const char *bp = (const char*) &pppoe->data[2];
220  ps++;
221  ps->type = TYPE_PPP_LCP;
222  ps->data = bp;
223  ps->len = intel16 (*(WORD*)(bp+2));
224  }
225  else if (proto == PPP_IPCP)
226  {
227  const char *bp = (const char*) &pppoe->data[2];
228  ps++;
229  ps->type = TYPE_PPP_IPCP;
230  ps->data = bp;
231  ps->len = intel16 (*(WORD*)(bp+2));
232  }
233  }
234  else if (intel16(type) < ETH_MAX_DATA) /* LLC unsupported */
235  {
236  ps++;
237  ps->type = TYPE_LLC_HEAD;
238  ps->len = intel16 (type);
239  ps->data = &pkt->eth.data[0];
240  }
241 
242  ps++;
243  ps->data = NULL;
244 }
245 
246 static void split_ip4 (struct pkt_split *ps, const in_Header *ip4)
247 {
248  unsigned ip_len, ip_ofs, head_len;
249  int opt_len;
250 
251  head_len = in_GetHdrLen (ip4);
252  opt_len = head_len - sizeof(*ip4);
253  ip_ofs = intel16 (ip4->frag_ofs);
254  ip_ofs = (ip_ofs & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */
255 
256  if (head_len < sizeof(*ip4))
257  goto quit;
258 
259  ps->type = TYPE_IP4;
260  ps->len = head_len;
261  ps->data = ip4;
262 
263  if (opt_len > 0)
264  {
265  ps++;
266  ps->type = TYPE_IP4_OPTIONS;
267  ps->data = (ip4 + 1);
268  ps->len = opt_len;
269  }
270 
271  if (ip_ofs)
272  {
273  ps++;
274  ps->type = TYPE_IP4_FRAG;
275  ps->data = (BYTE*)ip4 + head_len;
276  ps->len = intel16 (ip4->length) - head_len;
277  goto quit;
278  }
279 
280  if (ip4->proto == ICMP_PROTO)
281  {
282  ps++;
283  ps->type = TYPE_ICMP;
284  ps->data = (BYTE*)ip4 + head_len;
285  ps->len = intel16 (ip4->length) - head_len;
286  }
287 
288  else if (ip4->proto == IGMP_PROTO)
289  {
290  ps++;
291  ps->type = TYPE_IGMP;
292  ps->data = (BYTE*)ip4 + head_len;
293  ps->len = intel16 (ip4->length) - head_len;
294  }
295 
296  else if (ip4->proto == UDP_PROTO)
297  {
298  const udp_Header *udp = (const udp_Header*) ((BYTE*)ip4 + head_len);
299  unsigned len = intel16 (udp->length) - sizeof(*udp);
300 
301  ps++;
302  ps->type = TYPE_UDP_HEAD;
303  ps->data = (BYTE*)ip4 + head_len;
304  ps->len = sizeof (*udp);
305  ps++;
306  ps->type = TYPE_UDP_DATA;
307  ps->data = (BYTE*)ip4 + head_len + sizeof(*udp);
308  ps->len = min (len, intel16(ip4->length) - head_len - sizeof(*udp));
309  }
310 
311  else if (ip4->proto == TCP_PROTO)
312  {
313  const tcp_Header *tcp = (const tcp_Header*) ((BYTE*)ip4 + head_len);
314  unsigned ofs = tcp->offset << 2;
315  unsigned dlen;
316 
317  ip_len = intel16 (ip4->length) - sizeof(*ip4);
318  ps++;
319  ps->type = TYPE_TCP_HEAD;
320  ps->data = tcp;
321  ps->len = sizeof (*tcp);
322  if (ofs - sizeof(*tcp) > 0)
323  {
324  ps++;
325  ps->type = TYPE_TCP_OPTIONS;
326  ps->data = tcp + 1;
327  ps->len = ofs - sizeof(*tcp);
328  }
329  dlen = intel16 (ip4->length) - head_len - ofs;
330  dlen = min (dlen, ip_len);
331  ps++;
332  ps->type = TYPE_TCP_DATA;
333  ps->data = (const char*)tcp + ofs;
334  ps->len = dlen; /* may be 0 */
335  }
336 
337 quit:
338  ps++;
339  ps->data = NULL;
340 }
341 
342 static void split_ip6 (struct pkt_split *ps, const in6_Header *ip6)
343 {
344 #if defined(USE_IPV6)
345  const tcp_Header *tcp;
346  const ip6_RouteHdr *rh;
347  const BYTE *bp = (const BYTE*)ip6;
348  WORD ip_len = intel16 (ip6->len);
349  BYTE nxt_hd = ip6->next_hdr;
350  int ofs, len;
351 
352  ps->type = TYPE_IP6;
353  ps->len = sizeof(*ip6);
354  ps->data = ip6;
355  ps++;
356 
357  while (nxt_hd && (bp < (const BYTE*)ip6 + ip_len))
358  {
359  switch (nxt_hd)
360  {
361  case IP6_NEXT_TCP:
362  tcp = (const tcp_Header*) (ip6 + 1);
363  ofs = tcp->offset << 2;
364  ps->type = TYPE_TCP_HEAD;
365  ps->data = tcp;
366  ps->len = sizeof (*tcp);
367  if (ofs - sizeof(*tcp) > 0)
368  {
369  ps++;
370  ps->type = TYPE_TCP_OPTIONS;
371  ps->data = tcp + 1;
372  ps->len = ofs - sizeof(*tcp);
373  }
374  nxt_hd = 0; /* no next headers allowed */
375  break;
376 
377  case IP6_NEXT_UDP:
378  ps->type = TYPE_UDP_HEAD;
379  ps->data = ip6 + 1;
380  ps->len = sizeof (udp_Header);
381  nxt_hd = 0; /* no next headers allowed */
382  break;
383 
384  case IP6_NEXT_HOP:
385  rh = (struct ip6_RouteHdr*) (ip6 + 1);
386  len = (rh->hdrlen + 1) << 3;
387  ps->type = TYPE_IP6_HOP;
388  ps->data = rh;
389  ps->len = len;
390  bp += len;
391  nxt_hd = *bp;
392  break;
393 
394  case IP6_NEXT_ROUTING:
395  rh = (struct ip6_RouteHdr*) (ip6 + 1);
396  len = (rh->hdrlen + 1) << 3;
397  ps->type = TYPE_IP6_ROUTING;
398  ps->data = rh;
399  ps->len = len;
400  bp += len;
401  nxt_hd = *bp;
402  break;
403 
404  case IP6_NEXT_DEST:
405  rh = (struct ip6_RouteHdr*) (ip6 + 1);
406  len = (rh->hdrlen + 1) << 3;
407  ps->type = TYPE_IP6_DEST;
408  ps->data = rh;
409  ps->len = len;
410  bp += len;
411  nxt_hd = *bp;
412  break;
413 
414  case IP6_NEXT_ICMP:
415  rh = (struct ip6_RouteHdr*) (ip6 + 1);
416  len = (rh->hdrlen + 1) << 3;
417  ps->type = TYPE_IP6_ICMP;
418  ps->data = rh;
419  ps->len = len;
420  bp += len;
421  nxt_hd = 0;
422  break;
423 
424  case IP6_NEXT_NONE:
425  ps->type = TYPE_IP6_NONE;
426  ps->data = NULL;
427  ps->len = 0;
428  nxt_hd = 0;
429 
431  case IP6_NEXT_FRAGMENT:
432  case IP6_NEXT_ESP:
433  case IP6_NEXT_AUTH:
434  case IP6_NEXT_IPV6:
435  rh = (struct ip6_RouteHdr*) (ip6 + 1);
436  len = (rh->hdrlen + 1) << 3;
437  ps->type = TYPE_IP6_UNSUPP;
438  ps->data = NULL;
439  ps->len = 0;
440  bp += len;
441  nxt_hd = *bp;
442  break;
443 
444  case IP6_NEXT_COMP:
445  default:
446  ps->type = TYPE_IP6_UNSUPP;
447  ps->data = NULL;
448  ps->len = 0;
449  nxt_hd = 0;
450  }
451  ps++;
452  }
453 #else
454  ARGSUSED (ip6);
455 #endif /* USE_IPV6 */
456 
457  ps->data = NULL;
458 }
459 
460 #if defined(USE_DEBUG)
461 #if defined(USE_BSD_API)
462 
463 static const struct search_list names[] = {
464  { TYPE_TOKEN_HEAD, "token" },
465  { TYPE_FDDI_HEAD, "fddi" },
466  { TYPE_ETHER_HEAD, "ether" },
467  { TYPE_ARP, "arp" },
468  { TYPE_RARP, "rarp" },
469  { TYPE_PPPOE_DISC, "pppoe-disc" },
470  { TYPE_PPPOE_SESS, "pppoe-sess" },
471  { TYPE_PPP_LCP, "lcp" },
472  { TYPE_PPP_IPCP, "ipcp" },
473  { TYPE_LLC_HEAD, "llc" },
474  { TYPE_IP4, "ip4" },
475  { TYPE_IP4_OPTIONS, "ip4-opt" },
476  { TYPE_IP4_FRAG, "ip4-frag" },
477  { TYPE_ICMP, "icmp" },
478  { TYPE_IGMP, "igmp" },
479  { TYPE_UDP_HEAD, "udp" },
480  { TYPE_UDP_DATA, "udp-data" },
481  { TYPE_TCP_HEAD, "tcp" },
482  { TYPE_TCP_OPTIONS, "tcp-opt" },
483  { TYPE_TCP_DATA, "tcp-data" },
484  { TYPE_IP6, "ip6" },
485  { TYPE_IP6_HOP, "ip6-hop" },
486  { TYPE_IP6_IPV6, "ip6-ip6" },
487  { TYPE_IP6_ROUTING, "ip6-route" },
488  { TYPE_IP6_FRAGMENT,"ip6-frag" },
489  { TYPE_IP6_ESP, "ip6-esp" },
490  { TYPE_IP6_AUTH, "ip6-auth" },
491  { TYPE_IP6_ICMP, "icmp6" },
492  { TYPE_IP6_DEST, "ip6-dest" },
493  { TYPE_IP6_NONE, "ip6-none" },
494  { TYPE_IP6_UNSUPP, "ip6-unsupp" }
495  };
496 #endif
497 
498 void pkt_print_split_in (void)
499 {
500  const struct pkt_split *ps;
501 
502  SOCK_DEBUGF (("\nRx:\n"));
503  for (ps = pkt_get_split_in(); ps->data; ps++)
504  SOCK_DEBUGF (("%10s: %5u bytes\n",
505  list_lookup(ps->type, names, DIM(names)), ps->len));
506 }
507 
508 void pkt_print_split_out (void)
509 {
510  const struct pkt_split *ps;
511 
512  SOCK_DEBUGF (("\nTx:\n"));
513  for (ps = pkt_get_split_out(); ps->data; ps++)
514  SOCK_DEBUGF (("%10s: %5u bytes\n",
515  list_lookup(ps->type, names, DIM(names)), ps->len));
516 }
517 #endif /* USE_DEBUG */
518 #endif /* NEED_PKT_SPLIT */
Core definitions.
const char * list_lookup(DWORD type, const struct search_list *list, int num)
Search 'list' for 'type' and return it's name.
Definition: misc.c:929
Definition: ip.h:67
WORD _pktdevclass
Ethernet, Token, FDDI etc.
Definition: pcpkt.c:51
BOOL _pktserial
using serial driver, SLIP/PPP
Definition: pcpkt.c:54
static void split_ip6(struct pkt_split *, const in6_Header *)
Definition: split.c:342