Annotation of qemu/roms/ipxe/src/net/ipv4.c, revision 1.1.1.1

1.1       root        1: #include <string.h>
                      2: #include <stdint.h>
                      3: #include <stdlib.h>
                      4: #include <stdio.h>
                      5: #include <errno.h>
                      6: #include <byteswap.h>
                      7: #include <ipxe/list.h>
                      8: #include <ipxe/in.h>
                      9: #include <ipxe/arp.h>
                     10: #include <ipxe/if_ether.h>
                     11: #include <ipxe/iobuf.h>
                     12: #include <ipxe/netdevice.h>
                     13: #include <ipxe/ip.h>
                     14: #include <ipxe/tcpip.h>
                     15: #include <ipxe/dhcp.h>
                     16: #include <ipxe/settings.h>
                     17: 
                     18: /** @file
                     19:  *
                     20:  * IPv4 protocol
                     21:  *
                     22:  */
                     23: 
                     24: FILE_LICENCE ( GPL2_OR_LATER );
                     25: 
                     26: /* Unique IP datagram identification number */
                     27: static uint16_t next_ident = 0;
                     28: 
                     29: /** List of IPv4 miniroutes */
                     30: struct list_head ipv4_miniroutes = LIST_HEAD_INIT ( ipv4_miniroutes );
                     31: 
                     32: /** List of fragment reassembly buffers */
                     33: static LIST_HEAD ( frag_buffers );
                     34: 
                     35: /**
                     36:  * Add IPv4 minirouting table entry
                     37:  *
                     38:  * @v netdev           Network device
                     39:  * @v address          IPv4 address
                     40:  * @v netmask          Subnet mask
                     41:  * @v gateway          Gateway address (if any)
                     42:  * @ret miniroute      Routing table entry, or NULL
                     43:  */
                     44: static struct ipv4_miniroute * __malloc
                     45: add_ipv4_miniroute ( struct net_device *netdev, struct in_addr address,
                     46:                     struct in_addr netmask, struct in_addr gateway ) {
                     47:        struct ipv4_miniroute *miniroute;
                     48: 
                     49:        DBG ( "IPv4 add %s", inet_ntoa ( address ) );
                     50:        DBG ( "/%s ", inet_ntoa ( netmask ) );
                     51:        if ( gateway.s_addr )
                     52:                DBG ( "gw %s ", inet_ntoa ( gateway ) );
                     53:        DBG ( "via %s\n", netdev->name );
                     54: 
                     55:        /* Allocate and populate miniroute structure */
                     56:        miniroute = malloc ( sizeof ( *miniroute ) );
                     57:        if ( ! miniroute ) {
                     58:                DBG ( "IPv4 could not add miniroute\n" );
                     59:                return NULL;
                     60:        }
                     61: 
                     62:        /* Record routing information */
                     63:        miniroute->netdev = netdev_get ( netdev );
                     64:        miniroute->address = address;
                     65:        miniroute->netmask = netmask;
                     66:        miniroute->gateway = gateway;
                     67:                
                     68:        /* Add to end of list if we have a gateway, otherwise
                     69:         * to start of list.
                     70:         */
                     71:        if ( gateway.s_addr ) {
                     72:                list_add_tail ( &miniroute->list, &ipv4_miniroutes );
                     73:        } else {
                     74:                list_add ( &miniroute->list, &ipv4_miniroutes );
                     75:        }
                     76: 
                     77:        return miniroute;
                     78: }
                     79: 
                     80: /**
                     81:  * Delete IPv4 minirouting table entry
                     82:  *
                     83:  * @v miniroute                Routing table entry
                     84:  */
                     85: static void del_ipv4_miniroute ( struct ipv4_miniroute *miniroute ) {
                     86: 
                     87:        DBG ( "IPv4 del %s", inet_ntoa ( miniroute->address ) );
                     88:        DBG ( "/%s ", inet_ntoa ( miniroute->netmask ) );
                     89:        if ( miniroute->gateway.s_addr )
                     90:                DBG ( "gw %s ", inet_ntoa ( miniroute->gateway ) );
                     91:        DBG ( "via %s\n", miniroute->netdev->name );
                     92: 
                     93:        netdev_put ( miniroute->netdev );
                     94:        list_del ( &miniroute->list );
                     95:        free ( miniroute );
                     96: }
                     97: 
                     98: /**
                     99:  * Perform IPv4 routing
                    100:  *
                    101:  * @v dest             Final destination address
                    102:  * @ret dest           Next hop destination address
                    103:  * @ret miniroute      Routing table entry to use, or NULL if no route
                    104:  *
                    105:  * If the route requires use of a gateway, the next hop destination
                    106:  * address will be overwritten with the gateway address.
                    107:  */
                    108: static struct ipv4_miniroute * ipv4_route ( struct in_addr *dest ) {
                    109:        struct ipv4_miniroute *miniroute;
                    110:        int local;
                    111:        int has_gw;
                    112: 
                    113:        /* Never attempt to route the broadcast address */
                    114:        if ( dest->s_addr == INADDR_BROADCAST )
                    115:                return NULL;
                    116: 
                    117:        /* Find first usable route in routing table */
                    118:        list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
                    119:                if ( ! netdev_is_open ( miniroute->netdev ) )
                    120:                        continue;
                    121:                local = ( ( ( dest->s_addr ^ miniroute->address.s_addr )
                    122:                            & miniroute->netmask.s_addr ) == 0 );
                    123:                has_gw = ( miniroute->gateway.s_addr );
                    124:                if ( local || has_gw ) {
                    125:                        if ( ! local )
                    126:                                *dest = miniroute->gateway;
                    127:                        return miniroute;
                    128:                }
                    129:        }
                    130: 
                    131:        return NULL;
                    132: }
                    133: 
                    134: /**
                    135:  * Fragment reassembly counter timeout
                    136:  *
                    137:  * @v timer    Retry timer
                    138:  * @v over     If asserted, the timer is greater than @c MAX_TIMEOUT 
                    139:  */
                    140: static void ipv4_frag_expired ( struct retry_timer *timer __unused,
                    141:                                int over ) {
                    142:        if ( over ) {
                    143:                DBG ( "Fragment reassembly timeout" );
                    144:                /* Free the fragment buffer */
                    145:        }
                    146: }
                    147: 
                    148: /**
                    149:  * Free fragment buffer
                    150:  *
                    151:  * @v fragbug  Fragment buffer
                    152:  */
                    153: static void free_fragbuf ( struct frag_buffer *fragbuf ) {
                    154:        free ( fragbuf );
                    155: }
                    156: 
                    157: /**
                    158:  * Fragment reassembler
                    159:  *
                    160:  * @v iobuf            I/O buffer, fragment of the datagram
                    161:  * @ret frag_iob       Reassembled packet, or NULL
                    162:  */
                    163: static struct io_buffer * ipv4_reassemble ( struct io_buffer * iobuf ) {
                    164:        struct iphdr *iphdr = iobuf->data;
                    165:        struct frag_buffer *fragbuf;
                    166:        
                    167:        /**
                    168:         * Check if the fragment belongs to any fragment series
                    169:         */
                    170:        list_for_each_entry ( fragbuf, &frag_buffers, list ) {
                    171:                if ( fragbuf->ident == iphdr->ident &&
                    172:                     fragbuf->src.s_addr == iphdr->src.s_addr ) {
                    173:                        /**
                    174:                         * Check if the packet is the expected fragment
                    175:                         * 
                    176:                         * The offset of the new packet must be equal to the
                    177:                         * length of the data accumulated so far (the length of
                    178:                         * the reassembled I/O buffer
                    179:                         */
                    180:                        if ( iob_len ( fragbuf->frag_iob ) == 
                    181:                              ( iphdr->frags & IP_MASK_OFFSET ) ) {
                    182:                                /**
                    183:                                 * Append the contents of the fragment to the
                    184:                                 * reassembled I/O buffer
                    185:                                 */
                    186:                                iob_pull ( iobuf, sizeof ( *iphdr ) );
                    187:                                memcpy ( iob_put ( fragbuf->frag_iob,
                    188:                                                        iob_len ( iobuf ) ),
                    189:                                         iobuf->data, iob_len ( iobuf ) );
                    190:                                free_iob ( iobuf );
                    191: 
                    192:                                /** Check if the fragment series is over */
                    193:                                if ( ! ( iphdr->frags & IP_MASK_MOREFRAGS ) ) {
                    194:                                        iobuf = fragbuf->frag_iob;
                    195:                                        free_fragbuf ( fragbuf );
                    196:                                        return iobuf;
                    197:                                }
                    198: 
                    199:                        } else {
                    200:                                /* Discard the fragment series */
                    201:                                free_fragbuf ( fragbuf );
                    202:                                free_iob ( iobuf );
                    203:                        }
                    204:                        return NULL;
                    205:                }
                    206:        }
                    207:        
                    208:        /** Check if the fragment is the first in the fragment series */
                    209:        if ( iphdr->frags & IP_MASK_MOREFRAGS &&
                    210:                        ( ( iphdr->frags & IP_MASK_OFFSET ) == 0 ) ) {
                    211:        
                    212:                /** Create a new fragment buffer */
                    213:                fragbuf = ( struct frag_buffer* ) malloc ( sizeof( *fragbuf ) );
                    214:                fragbuf->ident = iphdr->ident;
                    215:                fragbuf->src = iphdr->src;
                    216: 
                    217:                /* Set up the reassembly I/O buffer */
                    218:                fragbuf->frag_iob = alloc_iob ( IP_FRAG_IOB_SIZE );
                    219:                iob_pull ( iobuf, sizeof ( *iphdr ) );
                    220:                memcpy ( iob_put ( fragbuf->frag_iob, iob_len ( iobuf ) ),
                    221:                         iobuf->data, iob_len ( iobuf ) );
                    222:                free_iob ( iobuf );
                    223: 
                    224:                /* Set the reassembly timer */
                    225:                timer_init ( &fragbuf->frag_timer, ipv4_frag_expired, NULL );
                    226:                start_timer_fixed ( &fragbuf->frag_timer, IP_FRAG_TIMEOUT );
                    227: 
                    228:                /* Add the fragment buffer to the list of fragment buffers */
                    229:                list_add ( &fragbuf->list, &frag_buffers );
                    230:        }
                    231:        
                    232:        return NULL;
                    233: }
                    234: 
                    235: /**
                    236:  * Add IPv4 pseudo-header checksum to existing checksum
                    237:  *
                    238:  * @v iobuf            I/O buffer
                    239:  * @v csum             Existing checksum
                    240:  * @ret csum           Updated checksum
                    241:  */
                    242: static uint16_t ipv4_pshdr_chksum ( struct io_buffer *iobuf, uint16_t csum ) {
                    243:        struct ipv4_pseudo_header pshdr;
                    244:        struct iphdr *iphdr = iobuf->data;
                    245:        size_t hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
                    246: 
                    247:        /* Build pseudo-header */
                    248:        pshdr.src = iphdr->src;
                    249:        pshdr.dest = iphdr->dest;
                    250:        pshdr.zero_padding = 0x00;
                    251:        pshdr.protocol = iphdr->protocol;
                    252:        pshdr.len = htons ( iob_len ( iobuf ) - hdrlen );
                    253: 
                    254:        /* Update the checksum value */
                    255:        return tcpip_continue_chksum ( csum, &pshdr, sizeof ( pshdr ) );
                    256: }
                    257: 
                    258: /**
                    259:  * Determine link-layer address
                    260:  *
                    261:  * @v dest             IPv4 destination address
                    262:  * @v src              IPv4 source address
                    263:  * @v netdev           Network device
                    264:  * @v ll_dest          Link-layer destination address buffer
                    265:  * @ret rc             Return status code
                    266:  */
                    267: static int ipv4_ll_addr ( struct in_addr dest, struct in_addr src,
                    268:                          struct net_device *netdev, uint8_t *ll_dest ) {
                    269:        struct ll_protocol *ll_protocol = netdev->ll_protocol;
                    270: 
                    271:        if ( dest.s_addr == INADDR_BROADCAST ) {
                    272:                /* Broadcast address */
                    273:                memcpy ( ll_dest, netdev->ll_broadcast,
                    274:                         ll_protocol->ll_addr_len );
                    275:                return 0;
                    276:        } else if ( IN_MULTICAST ( ntohl ( dest.s_addr ) ) ) {
                    277:                return ll_protocol->mc_hash ( AF_INET, &dest, ll_dest );
                    278:        } else {
                    279:                /* Unicast address: resolve via ARP */
                    280:                return arp_resolve ( netdev, &ipv4_protocol, &dest,
                    281:                                     &src, ll_dest );
                    282:        }
                    283: }
                    284: 
                    285: /**
                    286:  * Transmit IP packet
                    287:  *
                    288:  * @v iobuf            I/O buffer
                    289:  * @v tcpip            Transport-layer protocol
                    290:  * @v st_src           Source network-layer address
                    291:  * @v st_dest          Destination network-layer address
                    292:  * @v netdev           Network device to use if no route found, or NULL
                    293:  * @v trans_csum       Transport-layer checksum to complete, or NULL
                    294:  * @ret rc             Status
                    295:  *
                    296:  * This function expects a transport-layer segment and prepends the IP header
                    297:  */
                    298: static int ipv4_tx ( struct io_buffer *iobuf,
                    299:                     struct tcpip_protocol *tcpip_protocol,
                    300:                     struct sockaddr_tcpip *st_src,
                    301:                     struct sockaddr_tcpip *st_dest,
                    302:                     struct net_device *netdev,
                    303:                     uint16_t *trans_csum ) {
                    304:        struct iphdr *iphdr = iob_push ( iobuf, sizeof ( *iphdr ) );
                    305:        struct sockaddr_in *sin_src = ( ( struct sockaddr_in * ) st_src );
                    306:        struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
                    307:        struct ipv4_miniroute *miniroute;
                    308:        struct in_addr next_hop;
                    309:        uint8_t ll_dest[MAX_LL_ADDR_LEN];
                    310:        int rc;
                    311: 
                    312:        /* Fill up the IP header, except source address */
                    313:        memset ( iphdr, 0, sizeof ( *iphdr ) );
                    314:        iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
                    315:        iphdr->service = IP_TOS;
                    316:        iphdr->len = htons ( iob_len ( iobuf ) );       
                    317:        iphdr->ident = htons ( ++next_ident );
                    318:        iphdr->ttl = IP_TTL;
                    319:        iphdr->protocol = tcpip_protocol->tcpip_proto;
                    320:        iphdr->dest = sin_dest->sin_addr;
                    321: 
                    322:        /* Use routing table to identify next hop and transmitting netdev */
                    323:        next_hop = iphdr->dest;
                    324:        if ( sin_src )
                    325:                iphdr->src = sin_src->sin_addr;
                    326:        if ( ( next_hop.s_addr != INADDR_BROADCAST ) &&
                    327:             ( ! IN_MULTICAST ( ntohl ( next_hop.s_addr ) ) ) &&
                    328:             ( ( miniroute = ipv4_route ( &next_hop ) ) != NULL ) ) {
                    329:                iphdr->src = miniroute->address;
                    330:                netdev = miniroute->netdev;
                    331:        }
                    332:        if ( ! netdev ) {
                    333:                DBG ( "IPv4 has no route to %s\n", inet_ntoa ( iphdr->dest ) );
                    334:                rc = -ENETUNREACH;
                    335:                goto err;
                    336:        }
                    337: 
                    338:        /* Determine link-layer destination address */
                    339:        if ( ( rc = ipv4_ll_addr ( next_hop, iphdr->src, netdev,
                    340:                                   ll_dest ) ) != 0 ) {
                    341:                DBG ( "IPv4 has no link-layer address for %s: %s\n",
                    342:                      inet_ntoa ( next_hop ), strerror ( rc ) );
                    343:                goto err;
                    344:        }
                    345: 
                    346:        /* Fix up checksums */
                    347:        if ( trans_csum )
                    348:                *trans_csum = ipv4_pshdr_chksum ( iobuf, *trans_csum );
                    349:        iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
                    350: 
                    351:        /* Print IP4 header for debugging */
                    352:        DBG ( "IPv4 TX %s->", inet_ntoa ( iphdr->src ) );
                    353:        DBG ( "%s len %d proto %d id %04x csum %04x\n",
                    354:              inet_ntoa ( iphdr->dest ), ntohs ( iphdr->len ), iphdr->protocol,
                    355:              ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
                    356: 
                    357:        /* Hand off to link layer */
                    358:        if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest,
                    359:                             netdev->ll_addr ) ) != 0 ) {
                    360:                DBG ( "IPv4 could not transmit packet via %s: %s\n",
                    361:                      netdev->name, strerror ( rc ) );
                    362:                return rc;
                    363:        }
                    364: 
                    365:        return 0;
                    366: 
                    367:  err:
                    368:        free_iob ( iobuf );
                    369:        return rc;
                    370: }
                    371: 
                    372: /**
                    373:  * Process incoming packets
                    374:  *
                    375:  * @v iobuf    I/O buffer
                    376:  * @v netdev   Network device
                    377:  * @v ll_dest  Link-layer destination address
                    378:  * @v ll_source        Link-layer destination source
                    379:  *
                    380:  * This function expects an IP4 network datagram. It processes the headers 
                    381:  * and sends it to the transport layer.
                    382:  */
                    383: static int ipv4_rx ( struct io_buffer *iobuf,
                    384:                     struct net_device *netdev __unused,
                    385:                     const void *ll_dest __unused,
                    386:                     const void *ll_source __unused ) {
                    387:        struct iphdr *iphdr = iobuf->data;
                    388:        size_t hdrlen;
                    389:        size_t len;
                    390:        union {
                    391:                struct sockaddr_in sin;
                    392:                struct sockaddr_tcpip st;
                    393:        } src, dest;
                    394:        uint16_t csum;
                    395:        uint16_t pshdr_csum;
                    396:        int rc;
                    397: 
                    398:        /* Sanity check the IPv4 header */
                    399:        if ( iob_len ( iobuf ) < sizeof ( *iphdr ) ) {
                    400:                DBG ( "IPv4 packet too short at %zd bytes (min %zd bytes)\n",
                    401:                      iob_len ( iobuf ), sizeof ( *iphdr ) );
                    402:                goto err;
                    403:        }
                    404:        if ( ( iphdr->verhdrlen & IP_MASK_VER ) != IP_VER ) {
                    405:                DBG ( "IPv4 version %#02x not supported\n", iphdr->verhdrlen );
                    406:                goto err;
                    407:        }
                    408:        hdrlen = ( ( iphdr->verhdrlen & IP_MASK_HLEN ) * 4 );
                    409:        if ( hdrlen < sizeof ( *iphdr ) ) {
                    410:                DBG ( "IPv4 header too short at %zd bytes (min %zd bytes)\n",
                    411:                      hdrlen, sizeof ( *iphdr ) );
                    412:                goto err;
                    413:        }
                    414:        if ( hdrlen > iob_len ( iobuf ) ) {
                    415:                DBG ( "IPv4 header too long at %zd bytes "
                    416:                      "(packet is %zd bytes)\n", hdrlen, iob_len ( iobuf ) );
                    417:                goto err;
                    418:        }
                    419:        if ( ( csum = tcpip_chksum ( iphdr, hdrlen ) ) != 0 ) {
                    420:                DBG ( "IPv4 checksum incorrect (is %04x including checksum "
                    421:                      "field, should be 0000)\n", csum );
                    422:                goto err;
                    423:        }
                    424:        len = ntohs ( iphdr->len );
                    425:        if ( len < hdrlen ) {
                    426:                DBG ( "IPv4 length too short at %zd bytes "
                    427:                      "(header is %zd bytes)\n", len, hdrlen );
                    428:                goto err;
                    429:        }
                    430:        if ( len > iob_len ( iobuf ) ) {
                    431:                DBG ( "IPv4 length too long at %zd bytes "
                    432:                      "(packet is %zd bytes)\n", len, iob_len ( iobuf ) );
                    433:                goto err;
                    434:        }
                    435: 
                    436:        /* Print IPv4 header for debugging */
                    437:        DBG ( "IPv4 RX %s<-", inet_ntoa ( iphdr->dest ) );
                    438:        DBG ( "%s len %d proto %d id %04x csum %04x\n",
                    439:              inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
                    440:              ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
                    441: 
                    442:        /* Truncate packet to correct length, calculate pseudo-header
                    443:         * checksum and then strip off the IPv4 header.
                    444:         */
                    445:        iob_unput ( iobuf, ( iob_len ( iobuf ) - len ) );
                    446:        pshdr_csum = ipv4_pshdr_chksum ( iobuf, TCPIP_EMPTY_CSUM );
                    447:        iob_pull ( iobuf, hdrlen );
                    448: 
                    449:        /* Fragment reassembly */
                    450:        if ( ( iphdr->frags & htons ( IP_MASK_MOREFRAGS ) ) || 
                    451:             ( ( iphdr->frags & htons ( IP_MASK_OFFSET ) ) != 0 ) ) {
                    452:                /* Pass the fragment to ipv4_reassemble() which either
                    453:                 * returns a fully reassembled I/O buffer or NULL.
                    454:                 */
                    455:                iobuf = ipv4_reassemble ( iobuf );
                    456:                if ( ! iobuf )
                    457:                        return 0;
                    458:        }
                    459: 
                    460:        /* Construct socket addresses and hand off to transport layer */
                    461:        memset ( &src, 0, sizeof ( src ) );
                    462:        src.sin.sin_family = AF_INET;
                    463:        src.sin.sin_addr = iphdr->src;
                    464:        memset ( &dest, 0, sizeof ( dest ) );
                    465:        dest.sin.sin_family = AF_INET;
                    466:        dest.sin.sin_addr = iphdr->dest;
                    467:        if ( ( rc = tcpip_rx ( iobuf, iphdr->protocol, &src.st,
                    468:                               &dest.st, pshdr_csum ) ) != 0 ) {
                    469:                DBG ( "IPv4 received packet rejected by stack: %s\n",
                    470:                      strerror ( rc ) );
                    471:                return rc;
                    472:        }
                    473: 
                    474:        return 0;
                    475: 
                    476:  err:
                    477:        free_iob ( iobuf );
                    478:        return -EINVAL;
                    479: }
                    480: 
                    481: /** 
                    482:  * Check existence of IPv4 address for ARP
                    483:  *
                    484:  * @v netdev           Network device
                    485:  * @v net_addr         Network-layer address
                    486:  * @ret rc             Return status code
                    487:  */
                    488: static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
                    489:        const struct in_addr *address = net_addr;
                    490:        struct ipv4_miniroute *miniroute;
                    491: 
                    492:        list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
                    493:                if ( ( miniroute->netdev == netdev ) &&
                    494:                     ( miniroute->address.s_addr == address->s_addr ) ) {
                    495:                        /* Found matching address */
                    496:                        return 0;
                    497:                }
                    498:        }
                    499:        return -ENOENT;
                    500: }
                    501: 
                    502: /**
                    503:  * Convert IPv4 address to dotted-quad notation
                    504:  *
                    505:  * @v in       IP address
                    506:  * @ret string IP address in dotted-quad notation
                    507:  */
                    508: char * inet_ntoa ( struct in_addr in ) {
                    509:        static char buf[16]; /* "xxx.xxx.xxx.xxx" */
                    510:        uint8_t *bytes = ( uint8_t * ) &in;
                    511:        
                    512:        sprintf ( buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3] );
                    513:        return buf;
                    514: }
                    515: 
                    516: /**
                    517:  * Transcribe IP address
                    518:  *
                    519:  * @v net_addr IP address
                    520:  * @ret string IP address in dotted-quad notation
                    521:  *
                    522:  */
                    523: static const char * ipv4_ntoa ( const void *net_addr ) {
                    524:        return inet_ntoa ( * ( ( struct in_addr * ) net_addr ) );
                    525: }
                    526: 
                    527: /** IPv4 protocol */
                    528: struct net_protocol ipv4_protocol __net_protocol = {
                    529:        .name = "IP",
                    530:        .net_proto = htons ( ETH_P_IP ),
                    531:        .net_addr_len = sizeof ( struct in_addr ),
                    532:        .rx = ipv4_rx,
                    533:        .ntoa = ipv4_ntoa,
                    534: };
                    535: 
                    536: /** IPv4 TCPIP net protocol */
                    537: struct tcpip_net_protocol ipv4_tcpip_protocol __tcpip_net_protocol = {
                    538:        .name = "IPv4",
                    539:        .sa_family = AF_INET,
                    540:        .tx = ipv4_tx,
                    541: };
                    542: 
                    543: /** IPv4 ARP protocol */
                    544: struct arp_net_protocol ipv4_arp_protocol __arp_net_protocol = {
                    545:        .net_protocol = &ipv4_protocol,
                    546:        .check = ipv4_arp_check,
                    547: };
                    548: 
                    549: /******************************************************************************
                    550:  *
                    551:  * Settings
                    552:  *
                    553:  ******************************************************************************
                    554:  */
                    555: 
                    556: /** IPv4 address setting */
                    557: struct setting ip_setting __setting ( SETTING_IPv4 ) = {
                    558:        .name = "ip",
                    559:        .description = "IP address",
                    560:        .tag = DHCP_EB_YIADDR,
                    561:        .type = &setting_type_ipv4,
                    562: };
                    563: 
                    564: /** IPv4 subnet mask setting */
                    565: struct setting netmask_setting __setting ( SETTING_IPv4 ) = {
                    566:        .name = "netmask",
                    567:        .description = "Subnet mask",
                    568:        .tag = DHCP_SUBNET_MASK,
                    569:        .type = &setting_type_ipv4,
                    570: };
                    571: 
                    572: /** Default gateway setting */
                    573: struct setting gateway_setting __setting ( SETTING_IPv4 ) = {
                    574:        .name = "gateway",
                    575:        .description = "Default gateway",
                    576:        .tag = DHCP_ROUTERS,
                    577:        .type = &setting_type_ipv4,
                    578: };
                    579: 
                    580: /**
                    581:  * Create IPv4 routing table based on configured settings
                    582:  *
                    583:  * @ret rc             Return status code
                    584:  */
                    585: static int ipv4_create_routes ( void ) {
                    586:        struct ipv4_miniroute *miniroute;
                    587:        struct ipv4_miniroute *tmp;
                    588:        struct net_device *netdev;
                    589:        struct settings *settings;
                    590:        struct in_addr address = { 0 };
                    591:        struct in_addr netmask = { 0 };
                    592:        struct in_addr gateway = { 0 };
                    593: 
                    594:        /* Delete all existing routes */
                    595:        list_for_each_entry_safe ( miniroute, tmp, &ipv4_miniroutes, list )
                    596:                del_ipv4_miniroute ( miniroute );
                    597: 
                    598:        /* Create a route for each configured network device */
                    599:        for_each_netdev ( netdev ) {
                    600:                settings = netdev_settings ( netdev );
                    601:                /* Get IPv4 address */
                    602:                address.s_addr = 0;
                    603:                fetch_ipv4_setting ( settings, &ip_setting, &address );
                    604:                if ( ! address.s_addr )
                    605:                        continue;
                    606:                /* Get subnet mask */
                    607:                fetch_ipv4_setting ( settings, &netmask_setting, &netmask );
                    608:                /* Calculate default netmask, if necessary */
                    609:                if ( ! netmask.s_addr ) {
                    610:                        if ( IN_CLASSA ( ntohl ( address.s_addr ) ) ) {
                    611:                                netmask.s_addr = htonl ( IN_CLASSA_NET );
                    612:                        } else if ( IN_CLASSB ( ntohl ( address.s_addr ) ) ) {
                    613:                                netmask.s_addr = htonl ( IN_CLASSB_NET );
                    614:                        } else if ( IN_CLASSC ( ntohl ( address.s_addr ) ) ) {
                    615:                                netmask.s_addr = htonl ( IN_CLASSC_NET );
                    616:                        }
                    617:                }
                    618:                /* Get default gateway, if present */
                    619:                fetch_ipv4_setting ( settings, &gateway_setting, &gateway );
                    620:                /* Configure route */
                    621:                miniroute = add_ipv4_miniroute ( netdev, address,
                    622:                                                 netmask, gateway );
                    623:                if ( ! miniroute )
                    624:                        return -ENOMEM;
                    625:        }
                    626: 
                    627:        return 0;
                    628: }
                    629: 
                    630: /** IPv4 settings applicator */
                    631: struct settings_applicator ipv4_settings_applicator __settings_applicator = {
                    632:        .apply = ipv4_create_routes,
                    633: };
                    634: 
                    635: /* Drag in ICMP */
                    636: REQUIRE_OBJECT ( icmp );

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.