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