Changes in uspace/srv/net/inetsrv/inet_link.c [417a2ba1:4a5a18be] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/inetsrv/inet_link.c
r417a2ba1 r4a5a18be 43 43 #include <stdlib.h> 44 44 #include <str.h> 45 45 46 #include "addrobj.h" 46 47 #include "inetsrv.h" … … 48 49 #include "pdu.h" 49 50 50 static bool first_link = true; 51 static bool first_link6 = true; 52 53 static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock); 54 static uint16_t ip_ident = 0; 55 56 static int inet_iplink_recv(iplink_t *, iplink_recv_sdu_t *, ip_ver_t); 57 static inet_link_t *inet_link_get_by_id_locked(sysarg_t); 51 static int inet_link_open(service_id_t sid); 52 static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu); 58 53 59 54 static iplink_ev_ops_t inet_iplink_ev_ops = { … … 61 56 }; 62 57 63 static LIST_INITIALIZE(inet_links); 64 static FIBRIL_MUTEX_INITIALIZE(inet_links_lock); 65 66 static addr128_t link_local_node_ip = 67 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0, 0, 0}; 68 69 static void inet_link_local_node_ip(addr48_t mac_addr, 70 addr128_t ip_addr) 71 { 72 memcpy(ip_addr, link_local_node_ip, 16); 73 74 ip_addr[8] = mac_addr[0] ^ 0x02; 75 ip_addr[9] = mac_addr[1]; 76 ip_addr[10] = mac_addr[2]; 77 ip_addr[13] = mac_addr[3]; 78 ip_addr[14] = mac_addr[4]; 79 ip_addr[15] = mac_addr[5]; 80 } 81 82 static int inet_iplink_recv(iplink_t *iplink, iplink_recv_sdu_t *sdu, ip_ver_t ver) 83 { 58 static LIST_INITIALIZE(inet_link_list); 59 static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock); 60 61 static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu) 62 { 63 inet_packet_t packet; 64 int rc; 65 84 66 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_iplink_recv()"); 85 86 int rc; 87 inet_packet_t packet; 88 89 switch (ver) { 90 case ip_v4: 91 rc = inet_pdu_decode(sdu->data, sdu->size, &packet); 92 break; 93 case ip_v6: 94 rc = inet_pdu_decode6(sdu->data, sdu->size, &packet); 95 break; 96 default: 97 log_msg(LOG_DEFAULT, LVL_DEBUG, "invalid IP version"); 98 return EINVAL; 99 } 100 67 rc = inet_pdu_decode(sdu->data, sdu->size, &packet); 101 68 if (rc != EOK) { 102 69 log_msg(LOG_DEFAULT, LVL_DEBUG, "failed decoding PDU"); 103 70 return rc; 104 71 } 105 72 106 73 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet()"); 107 74 rc = inet_recv_packet(&packet); 108 75 log_msg(LOG_DEFAULT, LVL_DEBUG, "call inet_recv_packet -> %d", rc); 109 76 free(packet.data); 110 77 111 78 return rc; 79 } 80 81 static int inet_link_check_new(void) 82 { 83 bool already_known; 84 category_id_t iplink_cat; 85 service_id_t *svcs; 86 size_t count, i; 87 int rc; 88 89 fibril_mutex_lock(&inet_discovery_lock); 90 91 rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING); 92 if (rc != EOK) { 93 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed resolving category 'iplink'."); 94 fibril_mutex_unlock(&inet_discovery_lock); 95 return ENOENT; 96 } 97 98 rc = loc_category_get_svcs(iplink_cat, &svcs, &count); 99 if (rc != EOK) { 100 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting list of IP links."); 101 fibril_mutex_unlock(&inet_discovery_lock); 102 return EIO; 103 } 104 105 for (i = 0; i < count; i++) { 106 already_known = false; 107 108 list_foreach(inet_link_list, ilink_link) { 109 inet_link_t *ilink = list_get_instance(ilink_link, 110 inet_link_t, link_list); 111 if (ilink->svc_id == svcs[i]) { 112 already_known = true; 113 break; 114 } 115 } 116 117 if (!already_known) { 118 log_msg(LOG_DEFAULT, LVL_DEBUG, "Found IP link '%lu'", 119 (unsigned long) svcs[i]); 120 rc = inet_link_open(svcs[i]); 121 if (rc != EOK) 122 log_msg(LOG_DEFAULT, LVL_ERROR, "Could not open IP link."); 123 } 124 } 125 126 fibril_mutex_unlock(&inet_discovery_lock); 127 return EOK; 112 128 } 113 129 … … 131 147 if (ilink->svc_name != NULL) 132 148 free(ilink->svc_name); 133 134 149 free(ilink); 135 150 } 136 151 137 int inet_link_open(service_id_t sid)152 static int inet_link_open(service_id_t sid) 138 153 { 139 154 inet_link_t *ilink; 140 i net_addr_t iaddr;155 iplink_addr_t iaddr; 141 156 int rc; 142 157 … … 174 189 goto error; 175 190 } 176 177 /*178 * Get the MAC address of the link. If the link has a MAC179 * address, we assume that it supports NDP.180 */181 rc = iplink_get_mac48(ilink->iplink, &ilink->mac);182 ilink->mac_valid = (rc == EOK);183 191 184 192 log_msg(LOG_DEFAULT, LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name); 185 186 fibril_mutex_lock(&inet_links_lock); 187 188 if (inet_link_get_by_id_locked(sid) != NULL) { 189 fibril_mutex_unlock(&inet_links_lock); 190 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu already open", 191 sid); 192 rc = EEXIST; 193 goto error; 194 } 195 196 list_append(&ilink->link_list, &inet_links); 197 fibril_mutex_unlock(&inet_links_lock); 198 199 inet_addrobj_t *addr = NULL; 200 201 /* XXX FIXME Cannot rely on loopback being the first IP link service!! */ 202 if (first_link) { 203 addr = inet_addrobj_new(); 204 205 inet_naddr(&addr->naddr, 127, 0, 0, 1, 24); 206 first_link = false; 207 } 208 209 if (addr != NULL) { 210 addr->ilink = ilink; 211 addr->name = str_dup("v4a"); 212 213 rc = inet_addrobj_add(addr); 214 if (rc == EOK) { 215 inet_naddr_addr(&addr->naddr, &iaddr); 216 rc = iplink_addr_add(ilink->iplink, &iaddr); 217 if (rc != EOK) { 218 log_msg(LOG_DEFAULT, LVL_ERROR, 219 "Failed setting IPv4 address on internet link."); 220 inet_addrobj_remove(addr); 221 inet_addrobj_delete(addr); 222 } 223 } else { 224 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv4 address."); 225 inet_addrobj_delete(addr); 226 } 227 } 228 229 inet_addrobj_t *addr6 = NULL; 230 231 if (first_link6) { 232 addr6 = inet_addrobj_new(); 233 234 inet_naddr6(&addr6->naddr, 0, 0, 0, 0, 0, 0, 0, 1, 128); 235 first_link6 = false; 236 } else if (ilink->mac_valid) { 237 addr6 = inet_addrobj_new(); 238 239 addr128_t link_local; 240 inet_link_local_node_ip(ilink->mac, link_local); 241 242 inet_naddr_set6(link_local, 64, &addr6->naddr); 243 } 244 245 if (addr6 != NULL) { 246 addr6->ilink = ilink; 247 addr6->name = str_dup("v6a"); 248 249 rc = inet_addrobj_add(addr6); 250 if (rc == EOK) { 251 inet_naddr_addr(&addr6->naddr, &iaddr); 252 rc = iplink_addr_add(ilink->iplink, &iaddr); 253 if (rc != EOK) { 254 log_msg(LOG_DEFAULT, LVL_ERROR, 255 "Failed setting IPv6 address on internet link."); 256 inet_addrobj_remove(addr6); 257 inet_addrobj_delete(addr6); 258 } 259 } else { 260 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding IPv6 address."); 261 inet_addrobj_delete(addr6); 262 } 263 } 264 265 log_msg(LOG_DEFAULT, LVL_DEBUG, "Configured link '%s'.", ilink->svc_name); 193 list_append(&ilink->link_list, &inet_link_list); 194 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; 203 } 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 266 227 return EOK; 267 228 268 229 error: 269 230 if (ilink->iplink != NULL) 270 231 iplink_close(ilink->iplink); 271 272 232 inet_link_delete(ilink); 273 233 return rc; 274 234 } 275 235 276 /** Send IPv4 datagram over Internet link 277 * 278 * @param ilink Internet link 279 * @param lsrc Source IPv4 address 280 * @param ldest Destination IPv4 address 281 * @param dgram IPv4 datagram body 282 * @param proto Protocol 283 * @param ttl Time-to-live 284 * @param df Do-not-Fragment flag 285 * 286 * @return EOK on success 287 * @return ENOMEM when not enough memory to create the datagram 288 * @return ENOTSUP if networking mode is not supported 289 * 290 */ 291 int inet_link_send_dgram(inet_link_t *ilink, addr32_t lsrc, addr32_t ldest, 292 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df) 293 { 294 addr32_t src_v4; 295 ip_ver_t src_ver = inet_addr_get(&dgram->src, &src_v4, NULL); 296 if (src_ver != ip_v4) 297 return EINVAL; 298 299 addr32_t dest_v4;300 i p_ver_t dest_ver = inet_addr_get(&dgram->dest, &dest_v4, NULL);301 i f (dest_ver != ip_v4)302 return EINVAL;303 236 static void inet_link_cat_change_cb(void) 237 { 238 (void) inet_link_check_new(); 239 } 240 241 int inet_link_discovery_start(void) 242 { 243 int rc; 244 245 rc = loc_register_cat_change_cb(inet_link_cat_change_cb); 246 if (rc != EOK) { 247 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering callback for IP link " 248 "discovery (%d).", rc); 249 return rc; 250 } 251 252 return inet_link_check_new(); 253 } 254 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 304 264 /* 305 265 * Fill packet structure. Fragmentation is performed by 306 266 * inet_pdu_encode(). 307 267 */ 308 309 iplink_sdu_t sdu;310 311 sdu.src = lsrc;312 sdu.dest = ldest;313 314 inet_packet_t packet;315 316 268 packet.src = dgram->src; 317 269 packet.dest = dgram->dest; … … 319 271 packet.proto = proto; 320 272 packet.ttl = ttl; 321 322 /* Allocate identifier */323 fibril_mutex_lock(&ip_ident_lock);324 packet.ident = ++ip_ident;325 fibril_mutex_unlock(&ip_ident_lock);326 327 273 packet.df = df; 328 274 packet.data = dgram->data; 329 275 packet.size = dgram->size; 330 331 int rc; 332 size_t offs = 0; 333 276 277 sdu.lsrc.ipv4 = lsrc->ipv4; 278 sdu.ldest.ipv4 = ldest->ipv4; 279 280 offs = 0; 334 281 do { 335 282 /* Encode one fragment */ 336 337 size_t roffs; 338 rc = inet_pdu_encode(&packet, src_v4, dest_v4, offs, ilink->def_mtu, 339 &sdu.data, &sdu.size, &roffs); 283 rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data, 284 &sdu.size, &roffs); 340 285 if (rc != EOK) 341 286 return rc; 342 287 343 288 /* Send the PDU */ 344 289 rc = iplink_send(ilink->iplink, &sdu); 345 346 290 free(sdu.data); 291 347 292 offs = roffs; 348 293 } while (offs < packet.size); 349 294 350 295 return rc; 351 296 } 352 297 353 /** Send IPv6 datagram over Internet link 354 * 355 * @param ilink Internet link 356 * @param ldest Destination MAC address 357 * @param dgram IPv6 datagram body 358 * @param proto Next header 359 * @param ttl Hop limit 360 * @param df Do-not-Fragment flag (unused) 361 * 362 * @return EOK on success 363 * @return ENOMEM when not enough memory to create the datagram 364 * 365 */ 366 int inet_link_send_dgram6(inet_link_t *ilink, addr48_t ldest, 367 inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df) 368 { 369 addr128_t src_v6; 370 ip_ver_t src_ver = inet_addr_get(&dgram->src, NULL, &src_v6); 371 if (src_ver != ip_v6) 372 return EINVAL; 373 374 addr128_t dest_v6; 375 ip_ver_t dest_ver = inet_addr_get(&dgram->dest, NULL, &dest_v6); 376 if (dest_ver != ip_v6) 377 return EINVAL; 378 379 iplink_sdu6_t sdu6; 380 addr48(ldest, sdu6.dest); 381 382 /* 383 * Fill packet structure. Fragmentation is performed by 384 * inet_pdu_encode6(). 385 */ 386 387 inet_packet_t packet; 388 389 packet.src = dgram->src; 390 packet.dest = dgram->dest; 391 packet.tos = dgram->tos; 392 packet.proto = proto; 393 packet.ttl = ttl; 394 395 /* Allocate identifier */ 396 fibril_mutex_lock(&ip_ident_lock); 397 packet.ident = ++ip_ident; 398 fibril_mutex_unlock(&ip_ident_lock); 399 400 packet.df = df; 401 packet.data = dgram->data; 402 packet.size = dgram->size; 403 404 int rc; 405 size_t offs = 0; 406 407 do { 408 /* Encode one fragment */ 409 410 size_t roffs; 411 rc = inet_pdu_encode6(&packet, src_v6, dest_v6, offs, ilink->def_mtu, 412 &sdu6.data, &sdu6.size, &roffs); 413 if (rc != EOK) 414 return rc; 415 416 /* Send the PDU */ 417 rc = iplink_send6(ilink->iplink, &sdu6); 418 419 free(sdu6.data); 420 offs = roffs; 421 } while (offs < packet.size); 422 423 return rc; 424 } 425 426 static inet_link_t *inet_link_get_by_id_locked(sysarg_t link_id) 427 { 428 assert(fibril_mutex_is_locked(&inet_links_lock)); 429 430 list_foreach(inet_links, link_list, inet_link_t, ilink) { 431 if (ilink->svc_id == link_id) 298 inet_link_t *inet_link_get_by_id(sysarg_t link_id) 299 { 300 fibril_mutex_lock(&inet_discovery_lock); 301 302 list_foreach(inet_link_list, elem) { 303 inet_link_t *ilink = list_get_instance(elem, inet_link_t, 304 link_list); 305 306 if (ilink->svc_id == link_id) { 307 fibril_mutex_unlock(&inet_discovery_lock); 432 308 return ilink; 433 } 434 309 } 310 } 311 312 fibril_mutex_unlock(&inet_discovery_lock); 435 313 return NULL; 436 }437 438 inet_link_t *inet_link_get_by_id(sysarg_t link_id)439 {440 inet_link_t *ilink;441 442 fibril_mutex_lock(&inet_links_lock);443 ilink = inet_link_get_by_id_locked(link_id);444 fibril_mutex_unlock(&inet_links_lock);445 446 return ilink;447 }448 449 /** Get IDs of all links. */450 int inet_link_get_id_list(sysarg_t **rid_list, size_t *rcount)451 {452 sysarg_t *id_list;453 size_t count, i;454 455 fibril_mutex_lock(&inet_links_lock);456 count = list_count(&inet_links);457 458 id_list = calloc(count, sizeof(sysarg_t));459 if (id_list == NULL) {460 fibril_mutex_unlock(&inet_links_lock);461 return ENOMEM;462 }463 464 i = 0;465 list_foreach(inet_links, link_list, inet_link_t, ilink) {466 id_list[i++] = ilink->svc_id;467 log_msg(LOG_DEFAULT, LVL_NOTE, "add link to list");468 }469 470 fibril_mutex_unlock(&inet_links_lock);471 472 log_msg(LOG_DEFAULT, LVL_NOTE, "return %zu links", count);473 *rid_list = id_list;474 *rcount = count;475 476 return EOK;477 314 } 478 315
Note:
See TracChangeset
for help on using the changeset viewer.