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