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