1 /* raw_usrreq.c 4.18 82/07/24 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/protosw.h" 6 #include "../h/socket.h" 7 #include "../h/socketvar.h" 8 #include "../h/mtpr.h" 9 #include "../net/in.h" 10 #include "../net/in_systm.h" 11 #include "../net/if.h" 12 #include "../net/raw_cb.h" 13 #include <errno.h> 14 15 int rawqmaxlen = IFQ_MAXLEN; 16 17 /* 18 * Initialize raw connection block q. 19 */ 20 raw_init() 21 { 22 23 rawcb.rcb_next = rawcb.rcb_prev = &rawcb; 24 rawintrq.ifq_maxlen = IFQ_MAXLEN; 25 } 26 27 /* 28 * Raw protocol interface. 29 */ 30 raw_input(m0, proto, src, dst) 31 struct mbuf *m0; 32 struct sockproto *proto; 33 struct sockaddr *src, *dst; 34 { 35 register struct mbuf *m; 36 struct raw_header *rh; 37 int s; 38 39 /* 40 * Rip off an mbuf for a generic header. 41 */ 42 m = m_get(M_DONTWAIT); 43 if (m == 0) { 44 m_freem(m0); 45 return; 46 } 47 m->m_next = m0; 48 m->m_off = MMINOFF; 49 m->m_len = sizeof(struct raw_header); 50 rh = mtod(m, struct raw_header *); 51 rh->raw_dst = *dst; 52 rh->raw_src = *src; 53 rh->raw_proto = *proto; 54 55 /* 56 * Header now contains enough info to decide 57 * which socket to place packet in (if any). 58 * Queue it up for the raw protocol process 59 * running at software interrupt level. 60 */ 61 s = splimp(); 62 if (IF_QFULL(&rawintrq)) 63 m_freem(m); 64 else 65 IF_ENQUEUE(&rawintrq, m); 66 splx(s); 67 schednetisr(NETISR_RAW); 68 } 69 70 /* 71 * Raw protocol input routine. Process packets entered 72 * into the queue at interrupt time. Find the socket 73 * associated with the packet(s) and move them over. If 74 * nothing exists for this packet, drop it. 75 */ 76 rawintr() 77 { 78 int s; 79 struct mbuf *m; 80 register struct rawcb *rp; 81 register struct protosw *lproto; 82 register struct raw_header *rh; 83 struct socket *last; 84 85 next: 86 s = splimp(); 87 IF_DEQUEUE(&rawintrq, m); 88 splx(s); 89 if (m == 0) 90 return; 91 rh = mtod(m, struct raw_header *); 92 last = 0; 93 for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { 94 lproto = rp->rcb_socket->so_proto; 95 if (lproto->pr_family != rh->raw_proto.sp_family) 96 continue; 97 if (lproto->pr_protocol && 98 lproto->pr_protocol != rh->raw_proto.sp_protocol) 99 continue; 100 /* 101 * We assume the lower level routines have 102 * placed the address in a canonical format 103 * suitable for a structure comparison. 104 */ 105 #define equal(a1, a2) \ 106 (bcmp((caddr_t)&(a1), (caddr_t)&(a2), sizeof (struct sockaddr)) == 0) 107 if ((rp->rcb_flags & RAW_LADDR) && 108 !equal(rp->rcb_laddr, rh->raw_dst)) 109 continue; 110 if ((rp->rcb_flags & RAW_FADDR) && 111 !equal(rp->rcb_faddr, rh->raw_src)) 112 continue; 113 if (last) { 114 struct mbuf *n; 115 if ((n = m_copy(m->m_next, 0, (int)M_COPYALL)) == 0) 116 goto nospace; 117 if (sbappendaddr(&last->so_rcv, &rh->raw_src, n)==0) { 118 /* should notify about lost packet */ 119 m_freem(n); 120 goto nospace; 121 } 122 sorwakeup(last); 123 } 124 nospace: 125 last = rp->rcb_socket; 126 } 127 if (last) { 128 m = m_free(m); /* header */ 129 if (sbappendaddr(&last->so_rcv, &rh->raw_src, m) == 0) 130 goto drop; 131 sorwakeup(last); 132 goto next; 133 } 134 drop: 135 m_freem(m); 136 goto next; 137 } 138 139 raw_ctlinput(cmd, arg) 140 int cmd; 141 caddr_t arg; 142 { 143 144 if (cmd < 0 || cmd > PRC_NCMDS) 145 return; 146 } 147 148 /*ARGSUSED*/ 149 raw_usrreq(so, req, m, addr) 150 struct socket *so; 151 int req; 152 struct mbuf *m; 153 caddr_t addr; 154 { 155 register struct rawcb *rp = sotorawcb(so); 156 int error = 0; 157 158 if (rp == 0 && req != PRU_ATTACH) 159 return (EINVAL); 160 161 switch (req) { 162 163 /* 164 * Allocate a raw control block and fill in the 165 * necessary info to allow packets to be routed to 166 * the appropriate raw interface routine. 167 */ 168 case PRU_ATTACH: 169 if ((so->so_state & SS_PRIV) == 0) 170 return (EACCES); 171 if (rp) 172 return (EINVAL); 173 error = raw_attach(so, (struct sockaddr *)addr); 174 break; 175 176 /* 177 * Destroy state just before socket deallocation. 178 * Flush data or not depending on the options. 179 */ 180 case PRU_DETACH: 181 if (rp == 0) 182 return (ENOTCONN); 183 raw_detach(rp); 184 break; 185 186 /* 187 * If a socket isn't bound to a single address, 188 * the raw input routine will hand it anything 189 * within that protocol family (assuming there's 190 * nothing else around it should go to). 191 */ 192 case PRU_CONNECT: 193 if (rp->rcb_flags & RAW_FADDR) 194 return (EISCONN); 195 raw_connaddr(rp, (struct sockaddr *)addr); 196 soisconnected(so); 197 break; 198 199 case PRU_DISCONNECT: 200 if ((rp->rcb_flags & RAW_FADDR) == 0) 201 return (ENOTCONN); 202 raw_disconnect(rp); 203 soisdisconnected(so); 204 break; 205 206 /* 207 * Mark the connection as being incapable of further input. 208 */ 209 case PRU_SHUTDOWN: 210 socantsendmore(so); 211 break; 212 213 /* 214 * Ship a packet out. The appropriate raw output 215 * routine handles any massaging necessary. 216 */ 217 case PRU_SEND: 218 if (addr) { 219 if (rp->rcb_flags & RAW_FADDR) 220 return (EISCONN); 221 raw_connaddr(rp, (struct sockaddr *)addr); 222 } else if ((rp->rcb_flags & RAW_FADDR) == 0) 223 return (ENOTCONN); 224 error = (*so->so_proto->pr_output)(m, so); 225 if (addr) 226 rp->rcb_flags &= ~RAW_FADDR; 227 break; 228 229 case PRU_ABORT: 230 raw_disconnect(rp); 231 sofree(so); 232 soisdisconnected(so); 233 break; 234 235 /* 236 * Not supported. 237 */ 238 case PRU_ACCEPT: 239 case PRU_RCVD: 240 case PRU_CONTROL: 241 case PRU_SENSE: 242 case PRU_RCVOOB: 243 case PRU_SENDOOB: 244 error = EOPNOTSUPP; 245 break; 246 247 case PRU_SOCKADDR: 248 bcopy(addr, (caddr_t)&rp->rcb_laddr, sizeof (struct sockaddr)); 249 break; 250 251 default: 252 panic("raw_usrreq"); 253 } 254 return (error); 255 } 256