Ignore:
File:
1 edited

Legend:

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

    r4a5a18be r1f97352  
    4343#include <stdlib.h>
    4444#include <str.h>
    45 
     45#include <net/socket_codes.h>
    4646#include "addrobj.h"
    4747#include "inetsrv.h"
     
    4949#include "pdu.h"
    5050
    51 static int inet_link_open(service_id_t sid);
    52 static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
     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
     57static int inet_link_open(service_id_t);
     58static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, uint16_t);
    5359
    5460static iplink_ev_ops_t inet_iplink_ev_ops = {
     
    5965static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
    6066
    61 static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
    62 {
     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}
     82
     83static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, uint16_t af)
     84{
     85        log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
     86       
     87        int rc;
    6388        inet_packet_t packet;
    64         int rc;
    65 
    66         log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()");
    67         rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
     89       
     90        switch (af) {
     91        case AF_INET:
     92                rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
     93                break;
     94        case AF_INET6:
     95                rc = inet_pdu_decode6(sdu->data, sdu->size, &packet);
     96                break;
     97        default:
     98                log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid address family");
     99                return EINVAL;
     100        }
     101       
    68102        if (rc != EOK) {
    69103                log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU");
    70104                return rc;
    71105        }
    72 
     106       
    73107        log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()");
    74108        rc = inet_recv_packet(&packet);
    75109        log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc);
    76110        free(packet.data);
    77 
     111       
    78112        return rc;
    79113}
     
    147181        if (ilink->svc_name != NULL)
    148182                free(ilink->svc_name);
     183       
    149184        free(ilink);
    150185}
     
    153188{
    154189        inet_link_t *ilink;
    155         iplink_addr_t iaddr;
     190        inet_addr_t iaddr;
    156191        int rc;
    157192
     
    189224                goto error;
    190225        }
     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);
    191233
    192234        log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
    193235        list_append(&ilink->link_list, &inet_link_list);
    194236
    195         inet_addrobj_t *addr;
    196 
    197         static int first = 1;
    198         /* XXX For testing: set static IP address 10.0.2.15/24 */
    199         addr = inet_addrobj_new();
    200         if (first) {
    201                 addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1;
    202                 first = 0;
     237        inet_addrobj_t *addr = NULL;
     238       
     239        if (first_link) {
     240                addr = inet_addrobj_new();
     241               
     242                inet_naddr(&addr->naddr, 127, 0, 0, 1, 24);
     243                first_link = false;
    203244        } else {
    204                 addr->naddr.ipv4 = (10 << 24) + (0 << 16) + (2 << 8) + 15;
    205         }
    206         addr->naddr.bits = 24;
    207         addr->ilink = ilink;
    208         addr->name = str_dup("v4a");
    209         rc = inet_addrobj_add(addr);
    210         if (rc != EOK) {
    211                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
    212                 inet_addrobj_delete(addr);
    213                 /* XXX Roll back */
    214                 return rc;
    215         }
    216 
    217         iaddr.ipv4 = addr->naddr.ipv4;
    218         rc = iplink_addr_add(ilink->iplink, &iaddr);
    219         if (rc != EOK) {
    220                 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
    221                 inet_addrobj_remove(addr);
    222                 inet_addrobj_delete(addr);
    223                 /* XXX Roll back */
    224                 return rc;
    225         }
    226 
     245                /*
     246                 * FIXME
     247                 * Setting static IPv4 address for testing purposes:
     248                 * 10.0.2.15/24
     249                 */
     250                addr = inet_addrobj_new();
     251               
     252                inet_naddr(&addr->naddr, 10, 0, 2, 15, 24);
     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                }
     309        }
     310       
    227311        return EOK;
    228 
     312       
    229313error:
    230314        if (ilink->iplink != NULL)
    231315                iplink_close(ilink->iplink);
     316       
    232317        inet_link_delete(ilink);
    233318        return rc;
     
    253338}
    254339
    255 /** Send datagram over Internet link */
    256 int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
    257     inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
    258 {
    259         iplink_sdu_t sdu;
    260         inet_packet_t packet;
    261         int rc;
    262         size_t offs, roffs;
    263 
     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       
    264368        /*
    265369         * Fill packet structure. Fragmentation is performed by
    266370         * inet_pdu_encode().
    267371         */
     372       
     373        iplink_sdu_t sdu;
     374       
     375        sdu.src = lsrc;
     376        sdu.dest = ldest;
     377       
     378        inet_packet_t packet;
     379       
    268380        packet.src = dgram->src;
    269381        packet.dest = dgram->dest;
     
    271383        packet.proto = proto;
    272384        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       
    273391        packet.df = df;
    274392        packet.data = dgram->data;
    275393        packet.size = dgram->size;
    276 
    277         sdu.lsrc.ipv4 = lsrc->ipv4;
    278         sdu.ldest.ipv4 = ldest->ipv4;
    279 
    280         offs = 0;
     394       
     395        int rc;
     396        size_t offs = 0;
     397       
    281398        do {
    282399                /* Encode one fragment */
    283                 rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
    284                     &sdu.size, &roffs);
     400               
     401                size_t roffs;
     402                rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu,
     403                    &sdu.data, &sdu.size, &roffs);
    285404                if (rc != EOK)
    286405                        return rc;
    287 
     406               
    288407                /* Send the PDU */
    289408                rc = iplink_send(ilink->iplink, &sdu);
     409               
    290410                free(sdu.data);
    291 
    292411                offs = roffs;
    293412        } while (offs < packet.size);
    294 
     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);
     484                offs = roffs;
     485        } while (offs < packet.size);
     486       
    295487        return rc;
    296488}
Note: See TracChangeset for help on using the changeset viewer.