1 1.2 abs /* $NetBSD: pf-linux2.c,v 1.2 2020/10/27 17:07:14 abs Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * General Purpose AppleTalk Packet Filter Interface 5 1.1 christos * 6 1.1 christos * Copyright (c) 1992-1995, The University of Melbourne. 7 1.1 christos * All Rights Reserved. Permission to redistribute or 8 1.1 christos * use any part of this software for any purpose must 9 1.1 christos * be obtained in writing from the copyright owner. 10 1.1 christos * 11 1.1 christos * This software is supplied "as is" without express 12 1.1 christos * or implied warranty. 13 1.1 christos * 14 1.1 christos * djh (at) munnari.OZ.AU 15 1.1 christos * 16 1.1 christos * Supports: 17 1.1 christos * Linux SOCK_PACKET 18 1.1 christos * 19 1.1 christos * 20 1.1 christos * Modified for use with the linux-mopd port by Karl Maftoum 21 1.1 christos * u963870 (at) student.canberra.edu.au 22 1.1 christos * 23 1.1 christos */ 24 1.1 christos 25 1.1 christos #include "port.h" 26 1.2 abs __RCSID("$NetBSD: pf-linux2.c,v 1.2 2020/10/27 17:07:14 abs Exp $"); 27 1.1 christos 28 1.1 christos /* 29 1.1 christos * include header files 30 1.1 christos * 31 1.1 christos */ 32 1.1 christos 33 1.1 christos #include <stdio.h> 34 1.1 christos #include <fcntl.h> 35 1.1 christos #include <unistd.h> 36 1.1 christos #include <sys/types.h> 37 1.1 christos #include <sys/time.h> 38 1.1 christos #include <sys/ioctl.h> 39 1.1 christos #include <sys/file.h> 40 1.1 christos #include <sys/socket.h> 41 1.1 christos #include <net/if.h> 42 1.1 christos #include <sys/errno.h> 43 1.1 christos #include <linux/if_ether.h> 44 1.1 christos #include <netdb.h> 45 1.1 christos #include <ctype.h> 46 1.1 christos #include <string.h> 47 1.1 christos 48 1.1 christos #define MOPDEF_SUPRESS_EXTERN 49 1.1 christos #include "mopdef.h" 50 1.1 christos 51 1.1 christos /* 52 1.1 christos * definitions 53 1.1 christos * 54 1.1 christos */ 55 1.1 christos 56 1.1 christos #define READBUFSIZ 4096 57 1.1 christos #define NUMRDS 32 58 1.1 christos 59 1.1 christos struct RDS { 60 1.1 christos u_short dataLen; 61 1.1 christos u_char *dataPtr; 62 1.1 christos }; 63 1.1 christos 64 1.1 christos /* 65 1.1 christos * variables 66 1.1 christos * 67 1.1 christos */ 68 1.1 christos 69 1.1 christos struct socklist { 70 1.1 christos int iflen; 71 1.1 christos struct sockaddr sa; 72 1.1 christos } socklist[32]; 73 1.1 christos 74 1.1 christos struct ifreq ifr; 75 1.1 christos extern int errno; 76 1.1 christos extern int promisc; 77 1.1 christos 78 1.1 christos struct RDS RDS[NUMRDS]; 79 1.1 christos static int setup_pf(int, int, u_short); 80 1.1 christos 81 1.1 christos /* 82 1.1 christos * Open and initialize packet filter 83 1.1 christos * for a particular protocol type. 84 1.1 christos * 85 1.1 christos */ 86 1.1 christos 87 1.1 christos 88 1.1 christos int 89 1.2 abs pfInit(char *interface, int mode, u_short protocol, int typ) 90 1.1 christos { 91 1.1 christos int s; 92 1.1 christos int ioarg; 93 1.1 christos char device[64]; 94 1.1 christos unsigned long if_flags; 95 1.1 christos 96 1.1 christos 97 1.1 christos { u_short prot; 98 1.1 christos 99 1.1 christos prot = ((typ == TRANS_8023) ? htons(ETH_P_802_2) : htons(protocol)); 100 1.1 christos if ((s = socket(AF_INET, SOCK_PACKET, prot)) < 0) { 101 1.1 christos perror(interface); 102 1.1 christos return(-1); 103 1.1 christos } 104 1.1 christos if (s >= 32) { 105 1.1 christos close(s); 106 1.1 christos return(-1); 107 1.1 christos } 108 1.1 christos } 109 1.1 christos 110 1.1 christos /* 111 1.1 christos * set filter for protocol and type (IPTalk, Phase 1/2) 112 1.1 christos * 113 1.1 christos */ 114 1.1 christos 115 1.1 christos if (setup_pf(s, protocol, typ) < 0) 116 1.1 christos return(-1); 117 1.1 christos 118 1.1 christos /* 119 1.1 christos * set options, bind to underlying interface 120 1.1 christos * 121 1.1 christos */ 122 1.1 christos 123 1.1 christos strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name)); 124 1.1 christos 125 1.1 christos /* record socket interface name and length */ 126 1.1 christos strncpy(socklist[s].sa.sa_data, interface, sizeof(socklist[s].sa.sa_data)); 127 1.1 christos socklist[s].iflen = strlen(interface); 128 1.1 christos 129 1.1 christos return(s); 130 1.1 christos } 131 1.1 christos 132 1.1 christos /* 133 1.1 christos * establish protocol filter 134 1.1 christos * 135 1.1 christos */ 136 1.1 christos 137 1.1 christos static int 138 1.1 christos setup_pf(int s, int typ, u_short prot) 139 1.1 christos { 140 1.1 christos int ioarg; 141 1.1 christos u_short offset; 142 1.1 christos return(0); 143 1.1 christos } 144 1.1 christos 145 1.1 christos /* 146 1.1 christos * get the interface ethernet address 147 1.1 christos * 148 1.1 christos */ 149 1.1 christos 150 1.1 christos int 151 1.1 christos pfEthAddr(int s, char *interface, u_char *addr) 152 1.1 christos { 153 1.1 christos strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) -1); 154 1.1 christos ifr.ifr_name[sizeof(ifr.ifr_name)] = 0; 155 1.1 christos ifr.ifr_addr.sa_family = AF_INET; 156 1.1 christos if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) { 157 1.1 christos perror("SIOCGIFHWADDR"); 158 1.1 christos return(-1); 159 1.1 christos } 160 1.1 christos memcpy((char *)addr, ifr.ifr_hwaddr.sa_data, 6); 161 1.1 christos return(0); 162 1.1 christos } 163 1.1 christos 164 1.1 christos /* 165 1.1 christos * add a multicast address to the interface 166 1.1 christos * 167 1.1 christos */ 168 1.1 christos 169 1.1 christos int 170 1.1 christos pfAddMulti(int s, char *interface, u_char *addr) 171 1.1 christos { 172 1.1 christos int sock; 173 1.1 christos 174 1.1 christos strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1); 175 1.1 christos ifr.ifr_name[sizeof(ifr.ifr_name)] = 0; 176 1.1 christos 177 1.1 christos ifr.ifr_addr.sa_family = AF_UNSPEC; 178 1.1 christos bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); 179 1.1 christos 180 1.1 christos /* 181 1.1 christos * open a socket, temporarily, to use for SIOC* ioctls 182 1.1 christos * 183 1.1 christos */ 184 1.1 christos if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 185 1.1 christos perror("socket()"); 186 1.1 christos return(-1); 187 1.1 christos } 188 1.1 christos if (ioctl(sock, SIOCADDMULTI, (caddr_t)&ifr) < 0) { 189 1.1 christos perror("SIOCADDMULTI"); 190 1.1 christos close(sock); 191 1.1 christos return(-1); 192 1.1 christos } 193 1.1 christos close(sock); 194 1.1 christos 195 1.1 christos return(0); 196 1.1 christos } 197 1.1 christos 198 1.1 christos /* 199 1.1 christos * delete a multicast address from the interface 200 1.1 christos * 201 1.1 christos */ 202 1.1 christos 203 1.1 christos int 204 1.1 christos pfDelMulti(int s, char *interface, u_char *addr) 205 1.1 christos { 206 1.1 christos int sock; 207 1.1 christos 208 1.1 christos strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name) - 1); 209 1.1 christos ifr.ifr_name[sizeof(ifr.ifr_name)] = 0; 210 1.1 christos 211 1.1 christos ifr.ifr_addr.sa_family = AF_UNSPEC; 212 1.1 christos bcopy((char *)addr, ifr.ifr_addr.sa_data, 6); 213 1.1 christos 214 1.1 christos /* 215 1.1 christos * open a socket, temporarily, to use for SIOC* ioctls 216 1.1 christos * 217 1.1 christos */ 218 1.1 christos if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 219 1.1 christos perror("socket()"); 220 1.1 christos return(-1); 221 1.1 christos } 222 1.1 christos if (ioctl(sock, SIOCDELMULTI, (caddr_t)&ifr) < 0) { 223 1.1 christos perror("SIOCDELMULTI"); 224 1.1 christos close(sock); 225 1.1 christos return(-1); 226 1.1 christos } 227 1.1 christos close(sock); 228 1.1 christos 229 1.1 christos return(0); 230 1.1 christos } 231 1.1 christos 232 1.1 christos /* 233 1.1 christos * return 1 if ethernet interface capable of multiple opens 234 1.1 christos * 235 1.1 christos */ 236 1.1 christos 237 1.1 christos int 238 1.1 christos eth_mopen(int phase) 239 1.1 christos { 240 1.1 christos if (phase == 2) 241 1.1 christos return(0); 242 1.1 christos return(1); 243 1.1 christos } 244 1.1 christos 245 1.1 christos /* 246 1.1 christos * read a packet 247 1.1 christos * Read Data Structure describes packet(s) received 248 1.1 christos * 249 1.1 christos */ 250 1.1 christos 251 1.1 christos 252 1.1 christos 253 1.1 christos 254 1.1 christos int 255 1.1 christos pfRead(int fd, u_char *buf, int len) 256 1.1 christos { 257 1.1 christos int i, cc; 258 1.1 christos 259 1.1 christos int fromlen; 260 1.1 christos struct sockaddr sa; 261 1.1 christos 262 1.1 christos RDS[0].dataLen = 0; 263 1.1 christos fromlen = sizeof(struct sockaddr); 264 1.1 christos 265 1.1 christos if ((cc = recvfrom(fd, (char *)buf, len, 0, &sa, &fromlen)) <= 0) 266 1.1 christos return(cc); 267 1.1 christos 268 1.1 christos /* check if from right interface */ 269 1.1 christos for (i = socklist[fd].iflen-1; i >= 0; i--) 270 1.1 christos if (sa.sa_data[i] != socklist[fd].sa.sa_data[i]) 271 1.1 christos return(0); 272 1.1 christos 273 1.1 christos RDS[0].dataLen = cc; 274 1.1 christos RDS[0].dataPtr = buf; 275 1.1 christos RDS[1].dataLen = 0; 276 1.1 christos 277 1.1 christos return(cc); 278 1.1 christos } 279 1.1 christos 280 1.1 christos /* 281 1.1 christos * write a packet 282 1.1 christos * 283 1.1 christos */ 284 1.1 christos 285 1.1 christos int 286 1.1 christos pfWrite(int fd, u_char *buf, int len) 287 1.1 christos { 288 1.1 christos 289 1.1 christos if (sendto(fd, buf, len, 0, &socklist[fd].sa, sizeof(struct sockaddr)) == len) 290 1.1 christos return(len); 291 1.1 christos 292 1.1 christos return(-1); 293 1.1 christos } 294 1.1 christos 295 1.1 christos /* 296 1.1 christos * Return information to device.c how to open device. 297 1.1 christos * In this case the driver can handle both Ethernet type II and 298 1.1 christos * IEEE 802.3 frames (SNAP) in a single pfOpen. 299 1.1 christos */ 300 1.1 christos 301 1.1 christos int 302 1.1 christos pfTrans(char *interface) 303 1.1 christos { 304 1.1 christos return TRANS_ETHER+TRANS_8023; 305 1.1 christos } 306