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