ip6_output.c (171259) | ip6_output.c (171260) |
---|---|
1/* $FreeBSD: head/sys/netinet6/ip6_output.c 171259 2007-07-05 16:23:49Z delphij $ */ | 1/* $FreeBSD: head/sys/netinet6/ip6_output.c 171260 2007-07-05 16:29:40Z delphij $ */ |
2/* $KAME: ip6_output.c,v 1.279 2002/01/26 06:12:30 jinmei Exp $ */ 3 4/*- 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions --- 132 unchanged lines hidden (view full) --- 142 error = ip6_copyexthdr((mp), (caddr_t)(hp), \ 143 ((eh)->ip6e_len + 1) << 3); \ 144 if (error) \ 145 goto freehdrs; \ 146 } \ 147 } while (/*CONSTCOND*/ 0) 148 149/* | 2/* $KAME: ip6_output.c,v 1.279 2002/01/26 06:12:30 jinmei Exp $ */ 3 4/*- 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions --- 132 unchanged lines hidden (view full) --- 142 error = ip6_copyexthdr((mp), (caddr_t)(hp), \ 143 ((eh)->ip6e_len + 1) << 3); \ 144 if (error) \ 145 goto freehdrs; \ 146 } \ 147 } while (/*CONSTCOND*/ 0) 148 149/* |
150 * Form a chain of extension headers. | 150 * Form a chain of extension headers. |
151 * m is the extension header mbuf 152 * mp is the previous mbuf in the chain 153 * p is the next header 154 * i is the type of option. 155 */ 156#define MAKE_CHAIN(m, mp, p, i)\ 157 do {\ 158 if (m) {\ --- 54 unchanged lines hidden (view full) --- 213 struct secpolicy *sp = NULL; 214#endif /* IPSEC */ 215 216 ip6 = mtod(m, struct ip6_hdr *); 217 if (ip6 == NULL) { 218 printf ("ip6 is NULL"); 219 goto bad; 220 } | 151 * m is the extension header mbuf 152 * mp is the previous mbuf in the chain 153 * p is the next header 154 * i is the type of option. 155 */ 156#define MAKE_CHAIN(m, mp, p, i)\ 157 do {\ 158 if (m) {\ --- 54 unchanged lines hidden (view full) --- 213 struct secpolicy *sp = NULL; 214#endif /* IPSEC */ 215 216 ip6 = mtod(m, struct ip6_hdr *); 217 if (ip6 == NULL) { 218 printf ("ip6 is NULL"); 219 goto bad; 220 } |
221 | 221 |
222 finaldst = ip6->ip6_dst; 223 224 bzero(&exthdrs, sizeof(exthdrs)); 225 226 if (opt) { 227 /* Hop-by-Hop options header */ 228 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh); 229 /* Destination options header(1st part) */ --- 11 unchanged lines hidden (view full) --- 241 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1); 242 } 243 /* Routing header */ 244 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr); 245 /* Destination options header(2nd part) */ 246 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2); 247 } 248 | 222 finaldst = ip6->ip6_dst; 223 224 bzero(&exthdrs, sizeof(exthdrs)); 225 226 if (opt) { 227 /* Hop-by-Hop options header */ 228 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh); 229 /* Destination options header(1st part) */ --- 11 unchanged lines hidden (view full) --- 241 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1); 242 } 243 /* Routing header */ 244 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr); 245 /* Destination options header(2nd part) */ 246 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2); 247 } 248 |
249 /* | 249 /* |
250 * IPSec checking which handles several cases. 251 * FAST IPSEC: We re-injected the packet. 252 */ 253#ifdef IPSEC 254 switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp)) 255 { 256 case 1: /* Bad packet */ 257 goto freehdrs; 258 case -1: /* Do IPSec */ | 250 * IPSec checking which handles several cases. 251 * FAST IPSEC: We re-injected the packet. 252 */ 253#ifdef IPSEC 254 switch(ip6_ipsec_output(&m, inp, &flags, &error, &ifp, &sp)) 255 { 256 case 1: /* Bad packet */ 257 goto freehdrs; 258 case -1: /* Do IPSec */ |
259 needipsec = 1; | 259 needipsec = 1; |
260 case 0: /* No IPSec */ 261 default: 262 break; 263 } 264#endif /* IPSEC */ 265 266 /* 267 * Calculate the total length of the extension header chain. 268 * Keep the length of the unfragmentable part for fragmentation. 269 */ 270 optlen = 0; | 260 case 0: /* No IPSec */ 261 default: 262 break; 263 } 264#endif /* IPSEC */ 265 266 /* 267 * Calculate the total length of the extension header chain. 268 * Keep the length of the unfragmentable part for fragmentation. 269 */ 270 optlen = 0; |
271 if (exthdrs.ip6e_hbh) | 271 if (exthdrs.ip6e_hbh) |
272 optlen += exthdrs.ip6e_hbh->m_len; | 272 optlen += exthdrs.ip6e_hbh->m_len; |
273 if (exthdrs.ip6e_dest1) | 273 if (exthdrs.ip6e_dest1) |
274 optlen += exthdrs.ip6e_dest1->m_len; | 274 optlen += exthdrs.ip6e_dest1->m_len; |
275 if (exthdrs.ip6e_rthdr) | 275 if (exthdrs.ip6e_rthdr) |
276 optlen += exthdrs.ip6e_rthdr->m_len; 277 unfragpartlen = optlen + sizeof(struct ip6_hdr); 278 279 /* NOTE: we don't add AH/ESP length here. do that later. */ | 276 optlen += exthdrs.ip6e_rthdr->m_len; 277 unfragpartlen = optlen + sizeof(struct ip6_hdr); 278 279 /* NOTE: we don't add AH/ESP length here. do that later. */ |
280 if (exthdrs.ip6e_dest2) | 280 if (exthdrs.ip6e_dest2) |
281 optlen += exthdrs.ip6e_dest2->m_len; 282 283 /* 284 * If we need IPsec, or there is at least one extension header, 285 * separate IP6 header from the payload. 286 */ 287 if ((needipsec || optlen) && !hdrsplit) { 288 if ((error = ip6_splithdr(m, &exthdrs)) != 0) { --- 36 unchanged lines hidden (view full) --- 325 * and we insert headers accordingly. Finally, we should be getting: 326 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload] 327 * 328 * during the header composing process, "m" points to IPv6 header. 329 * "mprev" points to an extension header prior to esp. 330 */ 331 u_char *nexthdrp = &ip6->ip6_nxt; 332 mprev = m; | 281 optlen += exthdrs.ip6e_dest2->m_len; 282 283 /* 284 * If we need IPsec, or there is at least one extension header, 285 * separate IP6 header from the payload. 286 */ 287 if ((needipsec || optlen) && !hdrsplit) { 288 if ((error = ip6_splithdr(m, &exthdrs)) != 0) { --- 36 unchanged lines hidden (view full) --- 325 * and we insert headers accordingly. Finally, we should be getting: 326 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload] 327 * 328 * during the header composing process, "m" points to IPv6 header. 329 * "mprev" points to an extension header prior to esp. 330 */ 331 u_char *nexthdrp = &ip6->ip6_nxt; 332 mprev = m; |
333 | 333 |
334 /* 335 * we treat dest2 specially. this makes IPsec processing 336 * much easier. the goal here is to make mprev point the 337 * mbuf prior to dest2. 338 * 339 * result: IPv6 dest2 payload 340 * m and mprev will point to IPv6 header. 341 */ 342 if (exthdrs.ip6e_dest2) { 343 if (!hdrsplit) 344 panic("assumption failed: hdr not split"); 345 exthdrs.ip6e_dest2->m_next = m->m_next; 346 m->m_next = exthdrs.ip6e_dest2; 347 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; 348 ip6->ip6_nxt = IPPROTO_DSTOPTS; 349 } | 334 /* 335 * we treat dest2 specially. this makes IPsec processing 336 * much easier. the goal here is to make mprev point the 337 * mbuf prior to dest2. 338 * 339 * result: IPv6 dest2 payload 340 * m and mprev will point to IPv6 header. 341 */ 342 if (exthdrs.ip6e_dest2) { 343 if (!hdrsplit) 344 panic("assumption failed: hdr not split"); 345 exthdrs.ip6e_dest2->m_next = m->m_next; 346 m->m_next = exthdrs.ip6e_dest2; 347 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt; 348 ip6->ip6_nxt = IPPROTO_DSTOPTS; 349 } |
350 | 350 |
351 /* 352 * result: IPv6 hbh dest1 rthdr dest2 payload 353 * m will point to IPv6 header. mprev will point to the 354 * extension header prior to dest2 (rthdr in the above case). 355 */ 356 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS); 357 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp, 358 IPPROTO_DSTOPTS); 359 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp, 360 IPPROTO_ROUTING); | 351 /* 352 * result: IPv6 hbh dest1 rthdr dest2 payload 353 * m will point to IPv6 header. mprev will point to the 354 * extension header prior to dest2 (rthdr in the above case). 355 */ 356 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS); 357 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp, 358 IPPROTO_DSTOPTS); 359 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp, 360 IPPROTO_ROUTING); |
361 | 361 |
362#ifdef IPSEC 363 if (!needipsec) 364 goto skip_ipsec2; | 362#ifdef IPSEC 363 if (!needipsec) 364 goto skip_ipsec2; |
365 | 365 |
366 /* 367 * pointers after IPsec headers are not valid any more. 368 * other pointers need a great care too. 369 * (IPsec routines should not mangle mbufs prior to AH/ESP) 370 */ 371 exthdrs.ip6e_dest2 = NULL; | 366 /* 367 * pointers after IPsec headers are not valid any more. 368 * other pointers need a great care too. 369 * (IPsec routines should not mangle mbufs prior to AH/ESP) 370 */ 371 exthdrs.ip6e_dest2 = NULL; |
372 | 372 |
373 if (exthdrs.ip6e_rthdr) { 374 rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *); 375 segleft_org = rh->ip6r_segleft; 376 rh->ip6r_segleft = 0; 377 } | 373 if (exthdrs.ip6e_rthdr) { 374 rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *); 375 segleft_org = rh->ip6r_segleft; 376 rh->ip6r_segleft = 0; 377 } |
378 | 378 |
379 bzero(&state, sizeof(state)); 380 state.m = m; 381 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags, 382 &needipsectun); 383 m = state.m; 384 if (error) { 385 /* mbuf is already reclaimed in ipsec6_output_trans. */ 386 m = NULL; --- 9 unchanged lines hidden (view full) --- 396 /* FALLTHROUGH */ 397 case ENOENT: 398 /* don't show these error codes to the user */ 399 error = 0; 400 break; 401 } 402 goto bad; 403 } else if (!needipsectun) { | 379 bzero(&state, sizeof(state)); 380 state.m = m; 381 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags, 382 &needipsectun); 383 m = state.m; 384 if (error) { 385 /* mbuf is already reclaimed in ipsec6_output_trans. */ 386 m = NULL; --- 9 unchanged lines hidden (view full) --- 396 /* FALLTHROUGH */ 397 case ENOENT: 398 /* don't show these error codes to the user */ 399 error = 0; 400 break; 401 } 402 goto bad; 403 } else if (!needipsectun) { |
404 /* 405 * In the FAST IPSec case we have already | 404 /* 405 * In the FAST IPSec case we have already |
406 * re-injected the packet and it has been freed | 406 * re-injected the packet and it has been freed |
407 * by the ipsec_done() function. So, just clean | 407 * by the ipsec_done() function. So, just clean |
408 * up after ourselves. | 408 * up after ourselves. |
409 */ | 409 */ |
410 m = NULL; 411 goto done; | 410 m = NULL; 411 goto done; |
412 } | 412 } |
413 if (exthdrs.ip6e_rthdr) { 414 /* ah6_output doesn't modify mbuf chain */ 415 rh->ip6r_segleft = segleft_org; 416 } 417skip_ipsec2:; 418#endif /* IPSEC */ 419 420 /* --- 67 unchanged lines hidden (view full) --- 488 bzero((caddr_t)ro, sizeof(*ro)); 489 } 490 ro_pmtu = ro; 491 if (opt && opt->ip6po_rthdr) 492 ro = &opt->ip6po_route; 493 dst = (struct sockaddr_in6 *)&ro->ro_dst; 494 495again: | 413 if (exthdrs.ip6e_rthdr) { 414 /* ah6_output doesn't modify mbuf chain */ 415 rh->ip6r_segleft = segleft_org; 416 } 417skip_ipsec2:; 418#endif /* IPSEC */ 419 420 /* --- 67 unchanged lines hidden (view full) --- 488 bzero((caddr_t)ro, sizeof(*ro)); 489 } 490 ro_pmtu = ro; 491 if (opt && opt->ip6po_rthdr) 492 ro = &opt->ip6po_route; 493 dst = (struct sockaddr_in6 *)&ro->ro_dst; 494 495again: |
496 /* | 496 /* |
497 * if specified, try to fill in the traffic class field. 498 * do not override if a non-zero value is already set. 499 * we check the diffserv field and the ecn field separately. 500 */ 501 if (opt && opt->ip6po_tclass >= 0) { 502 int mask = 0; 503 504 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0) --- 58 unchanged lines hidden (view full) --- 563 /* FALLTHROUGH */ 564 case ENOENT: 565 /* don't show these error codes to the user */ 566 error = 0; 567 break; 568 } 569 goto bad; 570 } else { | 497 * if specified, try to fill in the traffic class field. 498 * do not override if a non-zero value is already set. 499 * we check the diffserv field and the ecn field separately. 500 */ 501 if (opt && opt->ip6po_tclass >= 0) { 502 int mask = 0; 503 504 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0) --- 58 unchanged lines hidden (view full) --- 563 /* FALLTHROUGH */ 564 case ENOENT: 565 /* don't show these error codes to the user */ 566 error = 0; 567 break; 568 } 569 goto bad; 570 } else { |
571 /* 572 * In the FAST IPSec case we have already | 571 /* 572 * In the FAST IPSec case we have already |
573 * re-injected the packet and it has been freed | 573 * re-injected the packet and it has been freed |
574 * by the ipsec_done() function. So, just clean | 574 * by the ipsec_done() function. So, just clean |
575 * up after ourselves. 576 */ 577 m = NULL; 578 goto done; 579 } 580 581 exthdrs.ip6e_ip6 = m; 582 } --- 470 unchanged lines hidden (view full) --- 1053sendorfree: 1054 m = m0->m_nextpkt; 1055 m0->m_nextpkt = 0; 1056 m_freem(m0); 1057 for (m0 = m; m; m = m0) { 1058 m0 = m->m_nextpkt; 1059 m->m_nextpkt = 0; 1060 if (error == 0) { | 575 * up after ourselves. 576 */ 577 m = NULL; 578 goto done; 579 } 580 581 exthdrs.ip6e_ip6 = m; 582 } --- 470 unchanged lines hidden (view full) --- 1053sendorfree: 1054 m = m0->m_nextpkt; 1055 m0->m_nextpkt = 0; 1056 m_freem(m0); 1057 for (m0 = m; m; m = m0) { 1058 m0 = m->m_nextpkt; 1059 m->m_nextpkt = 0; 1060 if (error == 0) { |
1061 /* Record statistics for this interface address. */ 1062 if (ia) { 1063 ia->ia_ifa.if_opackets++; 1064 ia->ia_ifa.if_obytes += m->m_pkthdr.len; 1065 } | 1061 /* Record statistics for this interface address. */ 1062 if (ia) { 1063 ia->ia_ifa.if_opackets++; 1064 ia->ia_ifa.if_obytes += m->m_pkthdr.len; 1065 } |
1066 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); 1067 } else 1068 m_freem(m); 1069 } 1070 1071 if (error == 0) 1072 ip6stat.ip6s_fragmented++; 1073 --- 2240 unchanged lines hidden --- | 1066 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt); 1067 } else 1068 m_freem(m); 1069 } 1070 1071 if (error == 0) 1072 ip6stat.ip6s_fragmented++; 1073 --- 2240 unchanged lines hidden --- |