Changeset 47f5a77 in mainline for uspace/srv/net/inetsrv/inet_link.c


Ignore:
Timestamp:
2013-07-17T08:46:06Z (12 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3a0a4d8
Parents:
cdc3afa (diff), 1d94e21 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

merge mainline changes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/inetsrv/inet_link.c

    rcdc3afa r47f5a77  
    4949#include "pdu.h"
    5050
     51static bool first_link = true;
     52static bool first_link6 = true;
     53
     54static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
     55static uint16_t ip_ident = 0;
     56
    5157static int inet_link_open(service_id_t);
    5258static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, uint16_t);
     
    5864static LIST_INITIALIZE(inet_link_list);
    5965static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
     66
     67static addr128_t link_local_node_ip =
     68    {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0};
     69
     70static void inet_link_local_node_ip(addr48_t mac_addr,
     71    addr128_t ip_addr)
     72{
     73        memcpy(ip_addr, link_local_node_ip, 16);
     74       
     75        ip_addr[8] = mac_addr[0] ^ 0x02;
     76        ip_addr[9] = mac_addr[1];
     77        ip_addr[10] = mac_addr[2];
     78        ip_addr[13] = mac_addr[3];
     79        ip_addr[14] = mac_addr[4];
     80        ip_addr[15] = mac_addr[5];
     81}
    6082
    6183static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, uint16_t af)
     
    159181        if (ilink->svc_name != NULL)
    160182                free(ilink->svc_name);
     183       
    161184        free(ilink);
    162185}
     
    201224                goto error;
    202225        }
     226       
     227        /*
     228         * Get the MAC address of the link. If the link has a MAC
     229         * address, we assume that it supports NDP.
     230         */
     231        rc = iplink_get_mac48(ilink->iplink, &ilink->mac);
     232        ilink->mac_valid = (rc == EOK);
    203233
    204234        log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
    205235        list_append(&ilink->link_list, &inet_link_list);
    206236
    207         inet_addrobj_t *addr;
    208         inet_addrobj_t *addr6;
    209 
    210         static int first = 1;
    211        
    212         addr = inet_addrobj_new();
    213         addr6 = inet_addrobj_new();
    214        
    215         if (first) {
     237        inet_addrobj_t *addr = NULL;
     238       
     239        if (first_link) {
     240                addr = inet_addrobj_new();
     241               
    216242                inet_naddr(&addr->naddr, 127, 0, 0, 1, 24);
    217                 inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128);
    218                 first = 0;
     243                first_link = false;
    219244        } else {
    220245                /*
    221246                 * FIXME
    222                  * Setting static IP addresses for testing purposes
     247                 * Setting static IPv4 address for testing purposes:
    223248                 * 10.0.2.15/24
    224                  * fd19:1680::4/120
    225249                 */
     250                addr = inet_addrobj_new();
     251               
    226252                inet_naddr(&addr->naddr, 10, 0, 2, 15, 24);
    227                 inet_naddr6(&addr6->naddr, 0xfd19, 0x1680, 0, 0, 0, 0, 0, 4, 120);
    228         }
    229        
    230         addr->ilink = ilink;
    231         addr6->ilink = ilink;
    232         addr->name = str_dup("v4a");
    233         addr6->name = str_dup("v6a");
    234        
    235         rc = inet_addrobj_add(addr);
    236         if (rc != EOK) {
    237                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address.");
    238                 inet_addrobj_delete(addr);
    239                 /* XXX Roll back */
    240                 return rc;
    241         }
    242        
    243         rc = inet_addrobj_add(addr6);
    244         if (rc != EOK) {
    245                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address.");
    246                 inet_addrobj_delete(addr6);
    247                 /* XXX Roll back */
    248                 return rc;
    249         }
    250        
    251         inet_naddr_addr(&addr->naddr, &iaddr);
    252         rc = iplink_addr_add(ilink->iplink, &iaddr);
    253         if (rc != EOK) {
    254                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IPv4 address on internet link.");
    255                 inet_addrobj_remove(addr);
    256                 inet_addrobj_delete(addr);
    257                 /* XXX Roll back */
    258                 return rc;
    259         }
    260        
    261         inet_naddr_addr(&addr6->naddr, &iaddr);
    262         rc = iplink_addr_add(ilink->iplink, &iaddr);
    263         if (rc != EOK) {
    264                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IPv6 address on internet link.");
    265                 inet_addrobj_remove(addr6);
    266                 inet_addrobj_delete(addr6);
    267                 /* XXX Roll back */
    268                 return rc;
     253        }
     254       
     255        if (addr != NULL) {
     256                addr->ilink = ilink;
     257                addr->name = str_dup("v4a");
     258               
     259                rc = inet_addrobj_add(addr);
     260                if (rc == EOK) {
     261                        inet_naddr_addr(&addr->naddr, &iaddr);
     262                        rc = iplink_addr_add(ilink->iplink, &iaddr);
     263                        if (rc != EOK) {
     264                                log_msg(LOG_DEFAULT, LVL_ERROR,
     265                                    "Failed setting IPv4 address on internet link.");
     266                                inet_addrobj_remove(addr);
     267                                inet_addrobj_delete(addr);
     268                        }
     269                } else {
     270                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address.");
     271                        inet_addrobj_delete(addr);
     272                }
     273        }
     274       
     275        inet_addrobj_t *addr6 = NULL;
     276       
     277        if (first_link6) {
     278                addr6 = inet_addrobj_new();
     279               
     280                inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128);
     281                first_link6 = false;
     282        } else if (ilink->mac_valid) {
     283                addr6 = inet_addrobj_new();
     284               
     285                addr128_t link_local;
     286                inet_link_local_node_ip(ilink->mac, link_local);
     287               
     288                inet_naddr_set6(link_local, 64, &addr6->naddr);
     289        }
     290       
     291        if (addr6 != NULL) {
     292                addr6->ilink = ilink;
     293                addr6->name = str_dup("v6a");
     294               
     295                rc = inet_addrobj_add(addr6);
     296                if (rc == EOK) {
     297                        inet_naddr_addr(&addr6->naddr, &iaddr);
     298                        rc = iplink_addr_add(ilink->iplink, &iaddr);
     299                        if (rc != EOK) {
     300                                log_msg(LOG_DEFAULT, LVL_ERROR,
     301                                    "Failed setting IPv6 address on internet link.");
     302                                inet_addrobj_remove(addr6);
     303                                inet_addrobj_delete(addr6);
     304                        }
     305                } else {
     306                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address.");
     307                        inet_addrobj_delete(addr6);
     308                }
    269309        }
    270310       
     
    298338}
    299339
    300 /** Send datagram over Internet link */
    301 int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
    302     inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
    303 {
     340/** Send IPv4 datagram over Internet link
     341 *
     342 * @param ilink Internet link
     343 * @param lsrc  Source IPv4 address
     344 * @param ldest Destination IPv4 address
     345 * @param dgram IPv4 datagram body
     346 * @param proto Protocol
     347 * @param ttl   Time-to-live
     348 * @param df    Do-not-Fragment flag
     349 *
     350 * @return EOK on success
     351 * @return ENOMEM when not enough memory to create the datagram
     352 * @return ENOTSUP if networking mode is not supported
     353 *
     354 */
     355int inet_link_send_dgram(inet_link_t *ilink, addr32_t lsrc, addr32_t ldest,
     356    inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
     357{
     358        addr32_t src_v4;
     359        uint16_t src_af = inet_addr_get(&dgram->src, &src_v4, NULL);
     360        if (src_af != AF_INET)
     361                return EINVAL;
     362       
     363        addr32_t dest_v4;
     364        uint16_t dest_af = inet_addr_get(&dgram->dest, &dest_v4, NULL);
     365        if (dest_af != AF_INET)
     366                return EINVAL;
     367       
    304368        /*
    305369         * Fill packet structure. Fragmentation is performed by
    306370         * inet_pdu_encode().
    307371         */
     372       
     373        iplink_sdu_t sdu;
     374       
     375        sdu.src = lsrc;
     376        sdu.dest = ldest;
    308377       
    309378        inet_packet_t packet;
     
    314383        packet.proto = proto;
    315384        packet.ttl = ttl;
     385       
     386        /* Allocate identifier */
     387        fibril_mutex_lock(&ip_ident_lock);
     388        packet.ident = ++ip_ident;
     389        fibril_mutex_unlock(&ip_ident_lock);
     390       
    316391        packet.df = df;
    317392        packet.data = dgram->data;
    318393        packet.size = dgram->size;
    319394       
    320         iplink_sdu_t sdu;
     395        int rc;
    321396        size_t offs = 0;
    322         int rc;
    323        
    324         sdu.src = *lsrc;
    325         sdu.dest = *ldest;
    326397       
    327398        do {
    328399                /* Encode one fragment */
     400               
    329401                size_t roffs;
    330                 rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
    331                     &sdu.size, &roffs);
     402                rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu,
     403                    &sdu.data, &sdu.size, &roffs);
    332404                if (rc != EOK)
    333405                        return rc;
     
    335407                /* Send the PDU */
    336408                rc = iplink_send(ilink->iplink, &sdu);
     409               
    337410                free(sdu.data);
    338                
     411                offs = roffs;
     412        } while (offs < packet.size);
     413       
     414        return rc;
     415}
     416
     417/** Send IPv6 datagram over Internet link
     418 *
     419 * @param ilink Internet link
     420 * @param ldest Destination MAC address
     421 * @param dgram IPv6 datagram body
     422 * @param proto Next header
     423 * @param ttl   Hop limit
     424 * @param df    Do-not-Fragment flag (unused)
     425 *
     426 * @return EOK on success
     427 * @return ENOMEM when not enough memory to create the datagram
     428 *
     429 */
     430int inet_link_send_dgram6(inet_link_t *ilink, addr48_t ldest,
     431    inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
     432{
     433        addr128_t src_v6;
     434        uint16_t src_af = inet_addr_get(&dgram->src, NULL, &src_v6);
     435        if (src_af != AF_INET6)
     436                return EINVAL;
     437       
     438        addr128_t dest_v6;
     439        uint16_t dest_af = inet_addr_get(&dgram->dest, NULL, &dest_v6);
     440        if (dest_af != AF_INET6)
     441                return EINVAL;
     442       
     443        iplink_sdu6_t sdu6;
     444        addr48(ldest, sdu6.dest);
     445       
     446        /*
     447         * Fill packet structure. Fragmentation is performed by
     448         * inet_pdu_encode6().
     449         */
     450       
     451        inet_packet_t packet;
     452       
     453        packet.src = dgram->src;
     454        packet.dest = dgram->dest;
     455        packet.tos = dgram->tos;
     456        packet.proto = proto;
     457        packet.ttl = ttl;
     458       
     459        /* Allocate identifier */
     460        fibril_mutex_lock(&ip_ident_lock);
     461        packet.ident = ++ip_ident;
     462        fibril_mutex_unlock(&ip_ident_lock);
     463       
     464        packet.df = df;
     465        packet.data = dgram->data;
     466        packet.size = dgram->size;
     467       
     468        int rc;
     469        size_t offs = 0;
     470       
     471        do {
     472                /* Encode one fragment */
     473               
     474                size_t roffs;
     475                rc = inet_pdu_encode6(&packet, src_v6, dest_v6, offs, ilink->def_mtu,
     476                    &sdu6.data, &sdu6.size, &roffs);
     477                if (rc != EOK)
     478                        return rc;
     479               
     480                /* Send the PDU */
     481                rc = iplink_send6(ilink->iplink, &sdu6);
     482               
     483                free(sdu6.data);
    339484                offs = roffs;
    340485        } while (offs < packet.size);
Note: See TracChangeset for help on using the changeset viewer.