1 /* 2 * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)ip_output.c 7.20 (Berkeley) 06/28/90 18 */ 19 20 #include "param.h" 21 #include "malloc.h" 22 #include "mbuf.h" 23 #include "errno.h" 24 #include "protosw.h" 25 #include "socket.h" 26 #include "socketvar.h" 27 28 #include "../net/if.h" 29 #include "../net/route.h" 30 31 #include "in.h" 32 #include "in_systm.h" 33 #include "ip.h" 34 #include "in_pcb.h" 35 #include "in_var.h" 36 #include "ip_var.h" 37 38 #ifdef vax 39 #include "machine/mtpr.h" 40 #endif 41 42 struct mbuf *ip_insertoptions(); 43 44 /* 45 * IP output. The packet in mbuf chain m contains a skeletal IP 46 * header (with len, off, ttl, proto, tos, src, dst). 47 * The mbuf chain containing the packet will be freed. 48 * The mbuf opt, if present, will not be freed. 49 */ 50 ip_output(m0, opt, ro, flags) 51 struct mbuf *m0; 52 struct mbuf *opt; 53 struct route *ro; 54 int flags; 55 { 56 register struct ip *ip, *mhip; 57 register struct ifnet *ifp; 58 register struct mbuf *m = m0; 59 register int hlen = sizeof (struct ip); 60 int len, off, error = 0; 61 struct route iproute; 62 struct sockaddr_in *dst; 63 struct in_ifaddr *ia; 64 65 if ((m->m_flags & M_PKTHDR) == 0) 66 panic("ip_output no HDR"); 67 if (opt) { 68 m = ip_insertoptions(m, opt, &len); 69 hlen = len; 70 } 71 ip = mtod(m, struct ip *); 72 /* 73 * Fill in IP header. 74 */ 75 if ((flags & IP_FORWARDING) == 0) { 76 ip->ip_v = IPVERSION; 77 ip->ip_off &= IP_DF; 78 ip->ip_id = htons(ip_id++); 79 ip->ip_hl = hlen >> 2; 80 } else { 81 hlen = ip->ip_hl << 2; 82 ipstat.ips_localout++; 83 } 84 /* 85 * Route packet. 86 */ 87 if (ro == 0) { 88 ro = &iproute; 89 bzero((caddr_t)ro, sizeof (*ro)); 90 } 91 dst = (struct sockaddr_in *)&ro->ro_dst; 92 /* 93 * If there is a cached route, 94 * check that it is to the same destination 95 * and is still up. If not, free it and try again. 96 */ 97 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 || 98 dst->sin_addr.s_addr != ip->ip_dst.s_addr)) { 99 RTFREE(ro->ro_rt); 100 ro->ro_rt = (struct rtentry *)0; 101 } 102 if (ro->ro_rt == 0) { 103 dst->sin_family = AF_INET; 104 dst->sin_len = sizeof(*dst); 105 dst->sin_addr = ip->ip_dst; 106 } 107 /* 108 * If routing to interface only, 109 * short circuit routing lookup. 110 */ 111 if (flags & IP_ROUTETOIF) { 112 113 ia = (struct in_ifaddr *)ifa_ifwithdstaddr((struct sockaddr *)dst); 114 if (ia == 0) 115 ia = in_iaonnetof(in_netof(ip->ip_dst)); 116 if (ia == 0) { 117 error = ENETUNREACH; 118 goto bad; 119 } 120 ifp = ia->ia_ifp; 121 } else { 122 if (ro->ro_rt == 0) 123 rtalloc(ro); 124 if (ro->ro_rt == 0) { 125 error = EHOSTUNREACH; 126 goto bad; 127 } 128 ia = (struct in_ifaddr *)ro->ro_rt->rt_ifa; 129 ifp = ro->ro_rt->rt_ifp; 130 ro->ro_rt->rt_use++; 131 if (ro->ro_rt->rt_flags & RTF_GATEWAY) 132 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway; 133 } 134 #ifndef notdef 135 /* 136 * If source address not specified yet, use address 137 * of outgoing interface. 138 */ 139 if (ip->ip_src.s_addr == INADDR_ANY) 140 ip->ip_src = IA_SIN(ia)->sin_addr; 141 #endif 142 /* 143 * Look for broadcast address and 144 * and verify user is allowed to send 145 * such a packet. 146 */ 147 if (in_broadcast(dst->sin_addr)) { 148 if ((ifp->if_flags & IFF_BROADCAST) == 0) { 149 error = EADDRNOTAVAIL; 150 goto bad; 151 } 152 if ((flags & IP_ALLOWBROADCAST) == 0) { 153 error = EACCES; 154 goto bad; 155 } 156 /* don't allow broadcast messages to be fragmented */ 157 if ((u_short)ip->ip_len > ifp->if_mtu) { 158 error = EMSGSIZE; 159 goto bad; 160 } 161 m->m_flags |= M_BCAST; 162 } 163 164 /* 165 * If small enough for interface, can just send directly. 166 */ 167 if ((u_short)ip->ip_len <= ifp->if_mtu) { 168 ip->ip_len = htons((u_short)ip->ip_len); 169 ip->ip_off = htons((u_short)ip->ip_off); 170 ip->ip_sum = 0; 171 ip->ip_sum = in_cksum(m, hlen); 172 error = (*ifp->if_output)(ifp, m, 173 (struct sockaddr *)dst, ro->ro_rt); 174 goto done; 175 } 176 ipstat.ips_fragmented++; 177 /* 178 * Too large for interface; fragment if possible. 179 * Must be able to put at least 8 bytes per fragment. 180 */ 181 if (ip->ip_off & IP_DF) { 182 error = EMSGSIZE; 183 goto bad; 184 } 185 len = (ifp->if_mtu - hlen) &~ 7; 186 if (len < 8) { 187 error = EMSGSIZE; 188 goto bad; 189 } 190 191 { 192 int mhlen, firstlen = len; 193 struct mbuf **mnext = &m->m_nextpkt; 194 195 /* 196 * Loop through length of segment after first fragment, 197 * make new header and copy data of each part and link onto chain. 198 */ 199 m0 = m; 200 mhlen = sizeof (struct ip); 201 for (off = hlen + len; off < (u_short)ip->ip_len; off += len) { 202 MGETHDR(m, M_DONTWAIT, MT_HEADER); 203 if (m == 0) { 204 error = ENOBUFS; 205 goto sendorfree; 206 } 207 m->m_data += max_linkhdr; 208 mhip = mtod(m, struct ip *); 209 *mhip = *ip; 210 if (hlen > sizeof (struct ip)) { 211 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 212 mhip->ip_hl = mhlen >> 2; 213 } 214 m->m_len = mhlen; 215 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); 216 if (ip->ip_off & IP_MF) 217 mhip->ip_off |= IP_MF; 218 if (off + len >= (u_short)ip->ip_len) 219 len = (u_short)ip->ip_len - off; 220 else 221 mhip->ip_off |= IP_MF; 222 mhip->ip_len = htons((u_short)(len + mhlen)); 223 m->m_next = m_copy(m0, off, len); 224 if (m->m_next == 0) { 225 error = ENOBUFS; /* ??? */ 226 goto sendorfree; 227 } 228 m->m_pkthdr.len = mhlen + len; 229 m->m_pkthdr.rcvif = (struct ifnet *)0; 230 mhip->ip_off = htons((u_short)mhip->ip_off); 231 mhip->ip_sum = 0; 232 mhip->ip_sum = in_cksum(m, mhlen); 233 *mnext = m; 234 mnext = &m->m_nextpkt; 235 ipstat.ips_ofragments++; 236 } 237 /* 238 * Update first fragment by trimming what's been copied out 239 * and updating header, then send each fragment (in order). 240 */ 241 m = m0; 242 m_adj(m, hlen + firstlen - (u_short)ip->ip_len); 243 m->m_pkthdr.len = hlen + firstlen; 244 ip->ip_len = htons((u_short)m->m_pkthdr.len); 245 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 246 ip->ip_sum = 0; 247 ip->ip_sum = in_cksum(m, hlen); 248 sendorfree: 249 for (m = m0; m; m = m0) { 250 m0 = m->m_nextpkt; 251 m->m_nextpkt = 0; 252 if (error == 0) 253 error = (*ifp->if_output)(ifp, m, 254 (struct sockaddr *)dst, ro->ro_rt); 255 else 256 m_freem(m); 257 } 258 } 259 done: 260 if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt) 261 RTFREE(ro->ro_rt); 262 return (error); 263 bad: 264 m_freem(m0); 265 goto done; 266 } 267 268 /* 269 * Insert IP options into preformed packet. 270 * Adjust IP destination as required for IP source routing, 271 * as indicated by a non-zero in_addr at the start of the options. 272 */ 273 struct mbuf * 274 ip_insertoptions(m, opt, phlen) 275 register struct mbuf *m; 276 struct mbuf *opt; 277 int *phlen; 278 { 279 register struct ipoption *p = mtod(opt, struct ipoption *); 280 struct mbuf *n; 281 register struct ip *ip = mtod(m, struct ip *); 282 unsigned optlen; 283 284 optlen = opt->m_len - sizeof(p->ipopt_dst); 285 if (optlen + (u_short)ip->ip_len > IP_MAXPACKET) 286 return (m); /* XXX should fail */ 287 if (p->ipopt_dst.s_addr) 288 ip->ip_dst = p->ipopt_dst; 289 if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) { 290 MGETHDR(n, M_DONTWAIT, MT_HEADER); 291 if (n == 0) 292 return (m); 293 n->m_pkthdr.len = m->m_pkthdr.len + optlen; 294 m->m_len -= sizeof(struct ip); 295 m->m_data += sizeof(struct ip); 296 n->m_next = m; 297 m = n; 298 m->m_len = optlen + sizeof(struct ip); 299 m->m_data += max_linkhdr; 300 bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); 301 } else { 302 m->m_data -= optlen; 303 m->m_len += optlen; 304 m->m_pkthdr.len += optlen; 305 ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip)); 306 } 307 ip = mtod(m, struct ip *); 308 bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen); 309 *phlen = sizeof(struct ip) + optlen; 310 ip->ip_len += optlen; 311 return (m); 312 } 313 314 /* 315 * Copy options from ip to jp, 316 * omitting those not copied during fragmentation. 317 */ 318 ip_optcopy(ip, jp) 319 struct ip *ip, *jp; 320 { 321 register u_char *cp, *dp; 322 int opt, optlen, cnt; 323 324 cp = (u_char *)(ip + 1); 325 dp = (u_char *)(jp + 1); 326 cnt = (ip->ip_hl << 2) - sizeof (struct ip); 327 for (; cnt > 0; cnt -= optlen, cp += optlen) { 328 opt = cp[0]; 329 if (opt == IPOPT_EOL) 330 break; 331 if (opt == IPOPT_NOP) 332 optlen = 1; 333 else 334 optlen = cp[IPOPT_OLEN]; 335 /* bogus lengths should have been caught by ip_dooptions */ 336 if (optlen > cnt) 337 optlen = cnt; 338 if (IPOPT_COPIED(opt)) { 339 bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen); 340 dp += optlen; 341 } 342 } 343 for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++) 344 *dp++ = IPOPT_EOL; 345 return (optlen); 346 } 347 348 /* 349 * IP socket option processing. 350 */ 351 ip_ctloutput(op, so, level, optname, mp) 352 int op; 353 struct socket *so; 354 int level, optname; 355 struct mbuf **mp; 356 { 357 register struct inpcb *inp = sotoinpcb(so); 358 register struct mbuf *m = *mp; 359 register int optval; 360 int error = 0; 361 362 if (level != IPPROTO_IP) 363 error = EINVAL; 364 else switch (op) { 365 366 case PRCO_SETOPT: 367 switch (optname) { 368 case IP_OPTIONS: 369 case IP_RETOPTS: 370 return (ip_pcbopts(optname, &inp->inp_options, m)); 371 372 case IP_TOS: 373 case IP_TTL: 374 case IP_RECVOPTS: 375 case IP_RECVRETOPTS: 376 case IP_RECVDSTADDR: 377 if (m->m_len != sizeof(int)) 378 error = EINVAL; 379 else { 380 optval = *mtod(m, int *); 381 switch (op) { 382 383 case IP_TOS: 384 inp->inp_ip.ip_tos = optval; 385 break; 386 387 case IP_TTL: 388 inp->inp_ip.ip_tos = optval; 389 break; 390 #define OPTSET(bit) \ 391 if (optval) \ 392 inp->inp_flags |= bit; \ 393 else \ 394 inp->inp_flags &= ~bit; 395 396 case IP_RECVOPTS: 397 OPTSET(INP_RECVOPTS); 398 break; 399 400 case IP_RECVRETOPTS: 401 OPTSET(INP_RECVRETOPTS); 402 break; 403 404 case IP_RECVDSTADDR: 405 OPTSET(INP_RECVDSTADDR); 406 break; 407 } 408 } 409 break; 410 #undef OPTSET 411 412 default: 413 error = EINVAL; 414 break; 415 } 416 if (m) 417 (void)m_free(m); 418 break; 419 420 case PRCO_GETOPT: 421 switch (optname) { 422 case IP_OPTIONS: 423 *mp = m = m_get(M_WAIT, MT_SOOPTS); 424 if (inp->inp_options) { 425 m->m_len = inp->inp_options->m_len; 426 bcopy(mtod(inp->inp_options, caddr_t), 427 mtod(m, caddr_t), (unsigned)m->m_len); 428 } else 429 m->m_len = 0; 430 break; 431 432 case IP_TOS: 433 case IP_TTL: 434 case IP_RECVOPTS: 435 case IP_RECVRETOPTS: 436 case IP_RECVDSTADDR: 437 *mp = m = m_get(M_WAIT, MT_SOOPTS); 438 m->m_len = sizeof(int); 439 switch (op) { 440 441 case IP_TOS: 442 optval = inp->inp_ip.ip_tos; 443 break; 444 445 case IP_TTL: 446 optval = inp->inp_ip.ip_tos; 447 break; 448 449 #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0) 450 451 case IP_RECVOPTS: 452 optval = OPTBIT(INP_RECVOPTS); 453 break; 454 455 case IP_RECVRETOPTS: 456 optval = OPTBIT(INP_RECVRETOPTS); 457 break; 458 459 case IP_RECVDSTADDR: 460 optval = OPTBIT(INP_RECVDSTADDR); 461 break; 462 } 463 *mtod(m, int *) = optval; 464 break; 465 466 default: 467 error = EINVAL; 468 break; 469 } 470 break; 471 } 472 return (error); 473 } 474 475 /* 476 * Set up IP options in pcb for insertion in output packets. 477 * Store in mbuf with pointer in pcbopt, adding pseudo-option 478 * with destination address if source routed. 479 */ 480 ip_pcbopts(pcbopt, m) 481 struct mbuf **pcbopt; 482 register struct mbuf *m; 483 { 484 register cnt, optlen; 485 register u_char *cp; 486 u_char opt; 487 488 /* turn off any old options */ 489 if (*pcbopt) 490 (void)m_free(*pcbopt); 491 *pcbopt = 0; 492 if (m == (struct mbuf *)0 || m->m_len == 0) { 493 /* 494 * Only turning off any previous options. 495 */ 496 if (m) 497 (void)m_free(m); 498 return (0); 499 } 500 501 #ifndef vax 502 if (m->m_len % sizeof(long)) 503 goto bad; 504 #endif 505 /* 506 * IP first-hop destination address will be stored before 507 * actual options; move other options back 508 * and clear it when none present. 509 */ 510 if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN]) 511 goto bad; 512 cnt = m->m_len; 513 m->m_len += sizeof(struct in_addr); 514 cp = mtod(m, u_char *) + sizeof(struct in_addr); 515 ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt); 516 bzero(mtod(m, caddr_t), sizeof(struct in_addr)); 517 518 for (; cnt > 0; cnt -= optlen, cp += optlen) { 519 opt = cp[IPOPT_OPTVAL]; 520 if (opt == IPOPT_EOL) 521 break; 522 if (opt == IPOPT_NOP) 523 optlen = 1; 524 else { 525 optlen = cp[IPOPT_OLEN]; 526 if (optlen <= IPOPT_OLEN || optlen > cnt) 527 goto bad; 528 } 529 switch (opt) { 530 531 default: 532 break; 533 534 case IPOPT_LSRR: 535 case IPOPT_SSRR: 536 /* 537 * user process specifies route as: 538 * ->A->B->C->D 539 * D must be our final destination (but we can't 540 * check that since we may not have connected yet). 541 * A is first hop destination, which doesn't appear in 542 * actual IP option, but is stored before the options. 543 */ 544 if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr)) 545 goto bad; 546 m->m_len -= sizeof(struct in_addr); 547 cnt -= sizeof(struct in_addr); 548 optlen -= sizeof(struct in_addr); 549 cp[IPOPT_OLEN] = optlen; 550 /* 551 * Move first hop before start of options. 552 */ 553 bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t), 554 sizeof(struct in_addr)); 555 /* 556 * Then copy rest of options back 557 * to close up the deleted entry. 558 */ 559 ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] + 560 sizeof(struct in_addr)), 561 (caddr_t)&cp[IPOPT_OFFSET+1], 562 (unsigned)cnt + sizeof(struct in_addr)); 563 break; 564 } 565 } 566 if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr)) 567 goto bad; 568 *pcbopt = m; 569 return (0); 570 571 bad: 572 (void)m_free(m); 573 return (EINVAL); 574 } 575