123186Smckusick /* 229146Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 332787Sbostic * All rights reserved. 423186Smckusick * 532787Sbostic * Redistribution and use in source and binary forms are permitted 6*34854Sbostic * provided that the above copyright notice and this paragraph are 7*34854Sbostic * duplicated in all such forms and that any documentation, 8*34854Sbostic * advertising materials, and other materials related to such 9*34854Sbostic * distribution and use acknowledge that the software was developed 10*34854Sbostic * by the University of California, Berkeley. The name of the 11*34854Sbostic * University may not be used to endorse or promote products derived 12*34854Sbostic * from this software without specific prior written permission. 13*34854Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34854Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34854Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1632787Sbostic * 17*34854Sbostic * @(#)raw_ip.c 7.4 (Berkeley) 06/29/88 1823186Smckusick */ 195123Swnj 2017062Sbloom #include "param.h" 2117062Sbloom #include "mbuf.h" 2217062Sbloom #include "socket.h" 2317062Sbloom #include "protosw.h" 2417062Sbloom #include "socketvar.h" 2517062Sbloom #include "errno.h" 2610894Ssam 276509Ssam #include "../net/if.h" 2813455Ssam #include "../net/route.h" 2910894Ssam #include "../net/raw_cb.h" 3010894Ssam 3117062Sbloom #include "in.h" 3217062Sbloom #include "in_systm.h" 3317062Sbloom #include "ip.h" 3417062Sbloom #include "ip_var.h" 355123Swnj 365123Swnj /* 375612Swnj * Raw interface to IP protocol. 385123Swnj */ 395612Swnj 4013455Ssam struct sockaddr_in ripdst = { AF_INET }; 4113455Ssam struct sockaddr_in ripsrc = { AF_INET }; 4213455Ssam struct sockproto ripproto = { PF_INET }; 435612Swnj /* 445612Swnj * Setup generic address and protocol structures 455612Swnj * for raw_input routine, then pass them along with 465612Swnj * mbuf chain. 475612Swnj */ 485123Swnj rip_input(m) 495123Swnj struct mbuf *m; 505123Swnj { 515612Swnj register struct ip *ip = mtod(m, struct ip *); 525123Swnj 535612Swnj ripproto.sp_protocol = ip->ip_p; 545646Ssam ripdst.sin_addr = ip->ip_dst; 555646Ssam ripsrc.sin_addr = ip->ip_src; 566529Ssam raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 576529Ssam (struct sockaddr *)&ripdst); 585123Swnj } 595123Swnj 605612Swnj /* 615612Swnj * Generate IP header and pass packet to ip_output. 625612Swnj * Tack on options user may have setup with control call. 635612Swnj */ 645612Swnj rip_output(m0, so) 655612Swnj struct mbuf *m0; 665612Swnj struct socket *so; 675123Swnj { 685612Swnj register struct mbuf *m; 695612Swnj register struct ip *ip; 706509Ssam int len = 0, error; 716509Ssam struct rawcb *rp = sotorawcb(so); 727156Swnj struct sockaddr_in *sin; 735123Swnj 745612Swnj /* 755612Swnj * Calculate data length and get an mbuf 765612Swnj * for IP header. 775612Swnj */ 785612Swnj for (m = m0; m; m = m->m_next) 795612Swnj len += m->m_len; 809642Ssam m = m_get(M_DONTWAIT, MT_HEADER); 815612Swnj if (m == 0) { 826509Ssam error = ENOBUFS; 836509Ssam goto bad; 845612Swnj } 855612Swnj 865612Swnj /* 875612Swnj * Fill in IP header as needed. 885612Swnj */ 895612Swnj m->m_off = MMAXOFF - sizeof(struct ip); 905612Swnj m->m_len = sizeof(struct ip); 915612Swnj m->m_next = m0; 925612Swnj ip = mtod(m, struct ip *); 9316798Skarels ip->ip_tos = 0; 9415714Skarels ip->ip_off = 0; 9521770Skarels ip->ip_p = rp->rcb_proto.sp_protocol; 965612Swnj ip->ip_len = sizeof(struct ip) + len; 977156Swnj if (rp->rcb_flags & RAW_LADDR) { 987156Swnj sin = (struct sockaddr_in *)&rp->rcb_laddr; 997156Swnj if (sin->sin_family != AF_INET) { 1006509Ssam error = EAFNOSUPPORT; 1016509Ssam goto bad; 1026509Ssam } 1037156Swnj ip->ip_src.s_addr = sin->sin_addr.s_addr; 1047156Swnj } else 1057156Swnj ip->ip_src.s_addr = 0; 1067156Swnj ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; 1075612Swnj ip->ip_ttl = MAXTTL; 10826037Skarels return (ip_output(m, rp->rcb_options, &rp->rcb_route, 10926037Skarels (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 1106509Ssam bad: 1116509Ssam m_freem(m); 1126509Ssam return (error); 1135123Swnj } 11426037Skarels 11526037Skarels /* 11626037Skarels * Raw IP socket option processing. 11726037Skarels */ 11826037Skarels rip_ctloutput(op, so, level, optname, m) 11926037Skarels int op; 12026037Skarels struct socket *so; 12126037Skarels int level, optname; 12226037Skarels struct mbuf **m; 12326037Skarels { 12426037Skarels int error = 0; 12526037Skarels register struct rawcb *rp = sotorawcb(so); 12626037Skarels 12726037Skarels if (level != IPPROTO_IP) 12826037Skarels error = EINVAL; 12926037Skarels else switch (op) { 13026037Skarels 13126037Skarels case PRCO_SETOPT: 13226037Skarels switch (optname) { 13326037Skarels case IP_OPTIONS: 13426037Skarels return (ip_pcbopts(&rp->rcb_options, *m)); 13526037Skarels 13626037Skarels default: 13726037Skarels error = EINVAL; 13826037Skarels break; 13926037Skarels } 14026037Skarels break; 14126037Skarels 14226037Skarels case PRCO_GETOPT: 14326037Skarels switch (optname) { 14426037Skarels case IP_OPTIONS: 14526037Skarels *m = m_get(M_WAIT, MT_SOOPTS); 14626037Skarels if (rp->rcb_options) { 14726037Skarels (*m)->m_off = rp->rcb_options->m_off; 14826037Skarels (*m)->m_len = rp->rcb_options->m_len; 14926037Skarels bcopy(mtod(rp->rcb_options, caddr_t), 15026386Skarels mtod(*m, caddr_t), (unsigned)(*m)->m_len); 15126037Skarels } else 15226037Skarels (*m)->m_len = 0; 15326037Skarels break; 15426037Skarels default: 15526037Skarels error = EINVAL; 15626037Skarels break; 15726037Skarels } 15826037Skarels break; 15926037Skarels } 16031649Smckusick if (op == PRCO_SETOPT && *m) 16126386Skarels (void)m_free(*m); 16226037Skarels return (error); 16326037Skarels } 164