00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "lwip/opt.h"
00043
00044
00045 #include "lwip/def.h"
00046 #include "lwip/mem.h"
00047 #include "lwip/ip.h"
00048 #include "lwip/ip_frag.h"
00049 #include "lwip/inet.h"
00050 #include "lwip/netif.h"
00051 #include "lwip/icmp.h"
00052 #include "lwip/udp.h"
00053 #include "lwip/tcp.h"
00054
00055 #include "lwip/stats.h"
00056
00057
00058 #define htons HTONS
00059 #define htonl HTONL
00060
00061
00062
00063 #include "lwip/snmp.h"
00064 #if LWIP_DHCP
00065 # include "lwip/dhcp.h"
00066 #endif
00067
00068
00069
00070
00071
00072
00073
00074 void
00075 ip_init(void)
00076 {
00077 }
00078
00079
00080
00081
00082
00083
00084
00085 #ifdef LWIP_DEBUG
00086 u8_t
00087 ip_lookup(void *header, struct netif *inp)
00088 {
00089 struct ip_hdr *iphdr;
00090
00091 iphdr = header;
00092
00093
00094 if(IPH_V(iphdr) != 4) {
00095 return 0;
00096 }
00097
00098
00099
00100 #if IP_REASSEMBLY == 0
00101
00102
00103
00104 #endif
00105
00106 #if IP_OPTIONS == 0
00107 if(IPH_HL(iphdr) != 5) {
00108 return 0;
00109 }
00110 #endif
00111
00112 switch(IPH_PROTO(iphdr)) {
00113 #if LWIP_UDP > 0
00114 case IP_PROTO_UDP:
00115 return udp_lookup(iphdr, inp);
00116 #endif
00117 #if LWIP_TCP > 0
00118 case IP_PROTO_TCP:
00119 return 1;
00120 #endif
00121 case IP_PROTO_ICMP:
00122 return 1;
00123 default:
00124 return 0;
00125 }
00126 }
00127 #endif
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 struct netif *
00138 ip_route(struct ip_addr *dest)
00139 {
00140 struct netif *netif;
00141
00142
00143 for(netif = netif_list; netif != NULL; netif = netif->next) {
00144
00145 if(ip_addr_maskcmp(dest, &(netif->ip_addr), &(netif->netmask))) {
00146
00147 return netif;
00148 }
00149 }
00150
00151 return netif_default;
00152 }
00153 #if IP_FORWARD
00154
00155
00156
00157
00158
00159
00160
00161
00162 static void
00163 ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp)
00164 {
00165 struct netif *netif;
00166
00167
00168
00169 netif = ip_route((struct ip_addr *)&(iphdr->dest));
00170 if(netif == NULL) {
00171 DEBUGF(IP_DEBUG, ("ip_forward: no forwarding route for 0x%lx found\n",
00172 iphdr->dest.addr));
00173 snmp_inc_ipnoroutes();
00174 return;
00175 }
00176
00177
00178 if(netif == inp) {
00179 DEBUGF(IP_DEBUG, ("ip_forward: not bouncing packets back on incoming interface.\n"));
00180 snmp_inc_ipnoroutes();
00181 return;
00182 }
00183
00184
00185 IPH_TTL_SET(iphdr, IPH_TTL(iphdr) - 1);
00186
00187 if(IPH_TTL(iphdr) == 0) {
00188
00189 if(IPH_PROTO(iphdr) != IP_PROTO_ICMP) {
00190 icmp_time_exceeded(p, ICMP_TE_TTL);
00191 snmp_inc_icmpouttimeexcds();
00192 }
00193 return;
00194 }
00195
00196
00197 if(IPH_CHKSUM(iphdr) >= htons(0xffff - 0x100)) {
00198 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100) + 1);
00199 } else {
00200 IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + htons(0x100));
00201 }
00202
00203 DEBUGF(IP_DEBUG, ("ip_forward: forwarding packet to 0x%lx\n",
00204 iphdr->dest.addr));
00205
00206 #ifdef IP_STATS
00207 ++lwip_stats.ip.fw;
00208 ++lwip_stats.ip.xmit;
00209 #endif
00210 snmp_inc_ipforwdatagrams();
00211
00212
00213
00214 netif->output(netif, p, (struct ip_addr *)&(iphdr->dest));
00215 }
00216 #endif
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 err_t
00230 ip_input(struct pbuf *p, struct netif *inp) {
00231 static struct ip_hdr *iphdr;
00232 static struct netif *netif;
00233 static u16_t iphdrlen;
00234
00235 #ifdef IP_STATS
00236 ++lwip_stats.ip.recv;
00237 #endif
00238 snmp_inc_ipinreceives();
00239
00240
00241 iphdr = p->payload;
00242 if(IPH_V(iphdr) != 4) {
00243 DEBUGF(IP_DEBUG | 1, ("IP packet dropped due to bad version number %d\n", IPH_V(iphdr)));
00244 #if IP_DEBUG
00245 ip_debug_print(p);
00246 #endif
00247 pbuf_free(p);
00248 #ifdef IP_STATS
00249 ++lwip_stats.ip.err;
00250 ++lwip_stats.ip.drop;
00251 #endif
00252 snmp_inc_ipunknownprotos();
00253 return ERR_OK;
00254 }
00255
00256 iphdrlen = IPH_HL(iphdr);
00257
00258 iphdrlen *= 4;
00259
00260
00261 if(iphdrlen > p->len) {
00262 DEBUGF(IP_DEBUG | 2, ("IP header (len %u) does not fit in first pbuf (len %u), IP packet droppped.\n",
00263 iphdrlen, p->len));
00264
00265 pbuf_free(p);
00266 #ifdef IP_STATS
00267 ++lwip_stats.ip.lenerr;
00268 ++lwip_stats.ip.drop;
00269 #endif
00270 snmp_inc_ipindiscards();
00271 return ERR_OK;
00272 }
00273
00274
00275 if(inet_chksum(iphdr, iphdrlen) != 0) {
00276
00277 DEBUGF(IP_DEBUG | 2, ("Checksum (0x%x) failed, IP packet dropped.\n", inet_chksum(iphdr, iphdrlen)));
00278 #if IP_DEBUG
00279 ip_debug_print(p);
00280 #endif
00281 pbuf_free(p);
00282 #ifdef IP_STATS
00283 ++lwip_stats.ip.chkerr;
00284 ++lwip_stats.ip.drop;
00285 #endif
00286 snmp_inc_ipindiscards();
00287 return ERR_OK;
00288 }
00289
00290
00291
00292 pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
00293
00294
00295 for(netif = netif_list; netif != NULL; netif = netif->next) {
00296
00297 DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%lx netif->ip_addr 0x%lx (0x%lx, 0x%lx, 0x%lx)\n",
00298 iphdr->dest.addr, netif->ip_addr.addr,
00299 iphdr->dest.addr & netif->netmask.addr,
00300 netif->ip_addr.addr & netif->netmask.addr,
00301 iphdr->dest.addr & ~(netif->netmask.addr)));
00302
00303
00304 if(!ip_addr_isany(&(netif->ip_addr)))
00305 {
00306
00307 if(ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
00308
00309 (ip_addr_isbroadcast(&(iphdr->dest), &(netif->netmask)) &&
00310 ip_addr_maskcmp(&(iphdr->dest), &(netif->ip_addr), &(netif->netmask))) ||
00311
00312 ip_addr_cmp(&(iphdr->dest), IP_ADDR_BROADCAST)) {
00313 DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
00314 netif->name[0], netif->name[1]));
00315
00316 break;
00317 }
00318 }
00319 }
00320 #if LWIP_DHCP
00321
00322
00323
00324 if(netif == NULL) {
00325
00326 if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
00327 DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: UDP packet to DHCP client port %u\n",
00328 ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest)));
00329 if (ntohs(((struct udp_hdr *)((u8_t *)iphdr + iphdrlen))->dest) == DHCP_CLIENT_PORT) {
00330 DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: DHCP packet accepted.\n"));
00331 netif = inp;
00332 }
00333 }
00334 }
00335 #endif
00336
00337 if(netif == NULL) {
00338
00339 DEBUGF(IP_DEBUG | DBG_TRACE | 1, ("ip_input: packet not for us.\n"));
00340 #if IP_FORWARD
00341
00342 if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask))) {
00343
00344 ip_forward(p, iphdr, inp);
00345 }
00346 else
00347 #endif
00348 {
00349 snmp_inc_ipindiscards();
00350 }
00351 pbuf_free(p);
00352 return ERR_OK;
00353 }
00354
00355 #if IP_REASSEMBLY
00356 if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
00357 DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04x tot_len=%u len=%u MF=%u offset=%u), calling ip_reass()\n", ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & htons(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
00358 p = ip_reass(p);
00359 if(p == NULL) {
00360 return ERR_OK;
00361 }
00362 iphdr = p->payload;
00363 }
00364 #else
00365 if((IPH_OFFSET(iphdr) & htons(IP_OFFMASK | IP_MF)) != 0) {
00366 pbuf_free(p);
00367 DEBUGF(IP_DEBUG | 2, ("IP packet dropped since it was fragmented (0x%x) (while IP_REASSEMBLY == 0).\n",
00368 ntohs(IPH_OFFSET(iphdr))));
00369 #ifdef IP_STATS
00370 ++lwip_stats.ip.opterr;
00371 ++lwip_stats.ip.drop;
00372 #endif
00373 snmp_inc_ipunknownprotos();
00374 return ERR_OK;
00375 }
00376 #endif
00377
00378 #if IP_OPTIONS == 0
00379 if (iphdrlen > IP_HLEN) {
00380 DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
00381 pbuf_free(p);
00382 #ifdef IP_STATS
00383 ++lwip_stats.ip.opterr;
00384 ++lwip_stats.ip.drop;
00385 #endif
00386 snmp_inc_ipunknownprotos();
00387 return ERR_OK;
00388 }
00389 #endif
00390
00391
00392 #if IP_DEBUG
00393 DEBUGF(IP_DEBUG, ("ip_input: \n"));
00394 ip_debug_print(p);
00395 DEBUGF(IP_DEBUG, ("ip_input: p->len %d p->tot_len %d\n", p->len, p->tot_len));
00396 #endif
00397
00398 switch(IPH_PROTO(iphdr)) {
00399 #if LWIP_UDP > 0
00400 case IP_PROTO_UDP:
00401 snmp_inc_ipindelivers();
00402 udp_input(p, inp);
00403 break;
00404 #endif
00405 #if LWIP_TCP > 0
00406 case IP_PROTO_TCP:
00407 snmp_inc_ipindelivers();
00408 tcp_input(p, inp);
00409 break;
00410 #endif
00411 case IP_PROTO_ICMP:
00412 snmp_inc_ipindelivers();
00413 icmp_input(p, inp);
00414 break;
00415 default:
00416
00417 if(!ip_addr_isbroadcast(&(iphdr->dest), &(inp->netmask)) &&
00418 !ip_addr_ismulticast(&(iphdr->dest))) {
00419 p->payload = iphdr;
00420 icmp_dest_unreach(p, ICMP_DUR_PROTO);
00421 }
00422 pbuf_free(p);
00423
00424 DEBUGF(IP_DEBUG | 2, ("Unsupported transport protocol %d\n", IPH_PROTO(iphdr)));
00425
00426 #ifdef IP_STATS
00427 ++lwip_stats.ip.proterr;
00428 ++lwip_stats.ip.drop;
00429 #endif
00430 snmp_inc_ipunknownprotos();
00431
00432 }
00433 return ERR_OK;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 err_t
00446 ip_output_if(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
00447 u8_t ttl,
00448 u8_t proto, struct netif *netif)
00449 {
00450 static struct ip_hdr *iphdr;
00451 static u16_t ip_id = 0;
00452
00453 snmp_inc_ipoutrequests();
00454
00455 if(dest != IP_HDRINCL) {
00456 if(pbuf_header(p, IP_HLEN)) {
00457 DEBUGF(IP_DEBUG | 2, ("ip_output: not enough room for IP header in pbuf\n"));
00458
00459 #ifdef IP_STATS
00460 ++lwip_stats.ip.err;
00461 #endif
00462 snmp_inc_ipoutdiscards();
00463 return ERR_BUF;
00464 }
00465
00466 iphdr = p->payload;
00467
00468 IPH_TTL_SET(iphdr, ttl);
00469 IPH_PROTO_SET(iphdr, proto);
00470
00471 ip_addr_set(&(iphdr->dest), dest);
00472
00473 IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
00474 IPH_LEN_SET(iphdr, htons(p->tot_len));
00475 IPH_OFFSET_SET(iphdr, htons(IP_DF));
00476 IPH_ID_SET(iphdr, htons(ip_id));
00477 ++ip_id;
00478
00479 if(ip_addr_isany(src)) {
00480 ip_addr_set(&(iphdr->src), &(netif->ip_addr));
00481 } else {
00482 ip_addr_set(&(iphdr->src), src);
00483 }
00484
00485 IPH_CHKSUM_SET(iphdr, 0);
00486 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
00487 } else {
00488 iphdr = p->payload;
00489 dest = &(iphdr->dest);
00490 }
00491
00492 #if IP_FRAG
00493
00494 if (netif->mtu && (p->tot_len > netif->mtu))
00495 return ip_frag(p,netif,dest);
00496 #endif
00497
00498 #ifdef IP_STATS
00499 lwip_stats.ip.xmit++;
00500 #endif
00501 DEBUGF(IP_DEBUG, ("ip_output_if: %c%c%u\n", netif->name[0], netif->name[1], netif->num));
00502 #if IP_DEBUG
00503 ip_debug_print(p);
00504 #endif
00505
00506 DEBUGF(IP_DEBUG, ("netif->output()"));
00507
00508 return netif->output(netif, p, dest);
00509 }
00510
00511
00512
00513
00514
00515
00516
00517 err_t
00518 ip_output(struct pbuf *p, struct ip_addr *src, struct ip_addr *dest,
00519 u8_t ttl, u8_t proto)
00520 {
00521 struct netif *netif;
00522
00523 if((netif = ip_route(dest)) == NULL) {
00524 DEBUGF(IP_DEBUG | 2, ("ip_output: No route to 0x%lx\n", dest->addr));
00525
00526 #ifdef IP_STATS
00527 ++lwip_stats.ip.rterr;
00528 #endif
00529 snmp_inc_ipoutdiscards();
00530 return ERR_RTE;
00531 }
00532
00533 return ip_output_if(p, src, dest, ttl, proto, netif);
00534 }
00535
00536 #if IP_DEBUG
00537 void
00538 ip_debug_print(struct pbuf *p)
00539 {
00540 struct ip_hdr *iphdr = p->payload;
00541 u8_t *payload;
00542
00543 payload = (u8_t *)iphdr + IP_HLEN;
00544
00545 DEBUGF(IP_DEBUG, ("IP header:\n"));
00546 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00547 DEBUGF(IP_DEBUG, ("|%2d |%2d | %2u | %4u | (v, hl, tos, len)\n",
00548 IPH_V(iphdr),
00549 IPH_HL(iphdr),
00550 IPH_TOS(iphdr),
00551 ntohs(IPH_LEN(iphdr))));
00552 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00553 DEBUGF(IP_DEBUG, ("| %5u |%u%u%u| %4u | (id, flags, offset)\n",
00554 ntohs(IPH_ID(iphdr)),
00555 ntohs(IPH_OFFSET(iphdr)) >> 15 & 1,
00556 ntohs(IPH_OFFSET(iphdr)) >> 14 & 1,
00557 ntohs(IPH_OFFSET(iphdr)) >> 13 & 1,
00558 ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK));
00559 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00560 DEBUGF(IP_DEBUG, ("| %2u | %2u | 0x%04x | (ttl, proto, chksum)\n",
00561 IPH_TTL(iphdr),
00562 IPH_PROTO(iphdr),
00563 ntohs(IPH_CHKSUM(iphdr))));
00564 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00565 DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (src)\n",
00566 ntohl(iphdr->src.addr) >> 24 & 0xff,
00567 ntohl(iphdr->src.addr) >> 16 & 0xff,
00568 ntohl(iphdr->src.addr) >> 8 & 0xff,
00569 ntohl(iphdr->src.addr) & 0xff));
00570 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00571 DEBUGF(IP_DEBUG, ("| %3ld | %3ld | %3ld | %3ld | (dest)\n",
00572 ntohl(iphdr->dest.addr) >> 24 & 0xff,
00573 ntohl(iphdr->dest.addr) >> 16 & 0xff,
00574 ntohl(iphdr->dest.addr) >> 8 & 0xff,
00575 ntohl(iphdr->dest.addr) & 0xff));
00576 DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
00577 }
00578 #endif
00579
00580
00581
00582
00583
00584