1 #ifdef sun 2 #define uint uxuint 3 #define ulong uxulong 4 #define ushort uxushort 5 #endif 6 #include <sys/types.h> 7 #include <sys/time.h> 8 #include <sys/socket.h> 9 #include <net/if.h> 10 #include <net/if_arp.h> 11 #include <netinet/in.h> 12 #include <netinet/tcp.h> 13 #include <arpa/inet.h> 14 #include <netdb.h> 15 #include <sys/ioctl.h> 16 #undef ulong 17 #undef ushort 18 #undef uint 19 20 #include "dat.h" 21 #include "fns.h" 22 #include "ip.h" 23 #include "error.h" 24 25 char Enotv4[] = "address not IPv4"; 26 27 static void 28 ipw6(uchar *a, ulong w) 29 { 30 memmove(a, v4prefix, IPv4off); 31 memmove(a+IPv4off, &w, IPv4addrlen); 32 } 33 34 int 35 so_socket(int type) 36 { 37 int fd, one; 38 39 switch(type) { 40 default: 41 error("bad protocol type"); 42 case S_TCP: 43 type = SOCK_STREAM; 44 break; 45 case S_UDP: 46 type = SOCK_DGRAM; 47 break; 48 } 49 50 fd = socket(AF_INET, type, 0); 51 if(fd < 0) 52 oserror(); 53 if(type == SOCK_DGRAM){ 54 one = 1; 55 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*)&one, sizeof(one)); 56 }else{ 57 one = 1; 58 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)); 59 } 60 return fd; 61 } 62 63 int 64 so_send(int sock, void *va, int len, void *hdr, int hdrlen) 65 { 66 int r; 67 struct sockaddr sa; 68 struct sockaddr_in *sin; 69 uchar *h = hdr; 70 71 osenter(); 72 if(hdr == 0) 73 r = write(sock, va, len); 74 else { 75 memset(&sa, 0, sizeof(sa)); 76 sin = (struct sockaddr_in*)&sa; 77 sin->sin_family = AF_INET; 78 switch(hdrlen){ 79 case OUdphdrlenv4: 80 memmove(&sin->sin_addr, h, 4); 81 memmove(&sin->sin_port, h+8, 2); 82 break; 83 case OUdphdrlen: 84 v6tov4((uchar*)&sin->sin_addr, h); 85 memmove(&sin->sin_port, h+2*IPaddrlen, 2); /* rport */ 86 break; 87 default: 88 v6tov4((uchar*)&sin->sin_addr, h); 89 memmove(&sin->sin_port, h+3*IPaddrlen, 2); 90 break; 91 } 92 r = sendto(sock, va, len, 0, &sa, sizeof(sa)); 93 } 94 osleave(); 95 return r; 96 } 97 98 int 99 so_recv(int sock, void *va, int len, void *hdr, int hdrlen) 100 { 101 int r; 102 socklen_t l; 103 struct sockaddr sa; 104 struct sockaddr_in *sin; 105 uchar h[Udphdrlen]; 106 107 osenter(); 108 if(hdr == 0) 109 r = read(sock, va, len); 110 else { 111 sin = (struct sockaddr_in*)&sa; 112 l = sizeof(sa); 113 r = recvfrom(sock, va, len, 0, &sa, &l); 114 if(r >= 0) { 115 memset(h, 0, sizeof(h)); 116 switch(hdrlen){ 117 case OUdphdrlenv4: 118 memmove(h, &sin->sin_addr, IPv4addrlen); 119 memmove(h+2*IPv4addrlen, &sin->sin_port, 2); 120 break; 121 case OUdphdrlen: 122 v4tov6(h, (uchar*)&sin->sin_addr); 123 memmove(h+2*IPaddrlen, &sin->sin_port, 2); 124 break; 125 default: 126 v4tov6(h, (uchar*)&sin->sin_addr); 127 memmove(h+3*IPaddrlen, &sin->sin_port, 2); 128 break; 129 } 130 131 /* alas there's no way to get the local addr/port correctly. Pretend. */ 132 memset(&sa, 0, sizeof(sa)); 133 getsockname(sock, &sa, &l); 134 switch(hdrlen){ 135 case OUdphdrlenv4: 136 memmove(h+IPv4addrlen, &sin->sin_addr, IPv4addrlen); 137 memmove(h+2*IPv4addrlen+2, &sin->sin_port, 2); 138 break; 139 case OUdphdrlen: 140 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 141 memmove(h+2*IPaddrlen+2, &sin->sin_port, 2); 142 break; 143 default: 144 v4tov6(h+IPaddrlen, (uchar*)&sin->sin_addr); 145 v4tov6(h+2*IPaddrlen, (uchar*)&sin->sin_addr); /* ifcaddr */ 146 memmove(h+3*IPaddrlen+2, &sin->sin_port, 2); 147 break; 148 } 149 memmove(hdr, h, hdrlen); 150 } 151 } 152 osleave(); 153 return r; 154 } 155 156 void 157 so_close(int sock) 158 { 159 close(sock); 160 } 161 162 void 163 so_connect(int fd, uchar *raddr, ushort rport) 164 { 165 int r; 166 struct sockaddr sa; 167 struct sockaddr_in *sin; 168 169 if(!isv4(raddr)) 170 error(Enotv4); 171 172 memset(&sa, 0, sizeof(sa)); 173 sin = (struct sockaddr_in*)&sa; 174 sin->sin_family = AF_INET; 175 hnputs(&sin->sin_port, rport); 176 memmove(&sin->sin_addr.s_addr, raddr+IPv4off, IPv4addrlen); 177 178 osenter(); 179 r = connect(fd, &sa, sizeof(sa)); 180 osleave(); 181 if(r < 0) 182 oserror(); 183 } 184 185 void 186 so_getsockname(int fd, uchar *laddr, ushort *lport) 187 { 188 socklen_t len; 189 struct sockaddr sa; 190 struct sockaddr_in *sin; 191 192 len = sizeof(sa); 193 if(getsockname(fd, &sa, &len) < 0) 194 oserror(); 195 196 sin = (struct sockaddr_in*)&sa; 197 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 198 error(Enotv4); 199 200 ipw6(laddr, sin->sin_addr.s_addr); 201 *lport = nhgets(&sin->sin_port); 202 } 203 204 void 205 so_listen(int fd) 206 { 207 int r; 208 209 osenter(); 210 r = listen(fd, 256); 211 osleave(); 212 if(r < 0) 213 oserror(); 214 } 215 216 int 217 so_accept(int fd, uchar *raddr, ushort *rport) 218 { 219 int nfd; 220 socklen_t len; 221 struct sockaddr sa; 222 struct sockaddr_in *sin; 223 224 sin = (struct sockaddr_in*)&sa; 225 226 len = sizeof(sa); 227 osenter(); 228 nfd = accept(fd, &sa, &len); 229 osleave(); 230 if(nfd < 0) 231 oserror(); 232 233 if(sin->sin_family != AF_INET || len != sizeof(*sin)) 234 error(Enotv4); 235 236 ipw6(raddr, sin->sin_addr.s_addr); 237 *rport = nhgets(&sin->sin_port); 238 return nfd; 239 } 240 241 void 242 so_bind(int fd, int su, uchar *addr, ushort port) 243 { 244 int i, one; 245 struct sockaddr sa; 246 struct sockaddr_in *sin; 247 248 sin = (struct sockaddr_in*)&sa; 249 250 one = 1; 251 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) { 252 oserrstr(up->genbuf, sizeof(up->genbuf)); 253 print("setsockopt: %s", up->genbuf); 254 } 255 256 if(su) { 257 for(i = 600; i < 1024; i++) { 258 memset(&sa, 0, sizeof(sa)); 259 sin->sin_family = AF_INET; 260 memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); 261 hnputs(&sin->sin_port, i); 262 263 if(bind(fd, &sa, sizeof(sa)) >= 0) 264 return; 265 } 266 oserror(); 267 } 268 269 memset(&sa, 0, sizeof(sa)); 270 sin->sin_family = AF_INET; 271 memmove(&sin->sin_addr.s_addr, addr+IPv4off, IPv4addrlen); 272 hnputs(&sin->sin_port, port); 273 274 if(bind(fd, &sa, sizeof(sa)) < 0) 275 oserror(); 276 } 277 278 int 279 so_gethostbyname(char *host, char**hostv, int n) 280 { 281 int i; 282 char buf[32]; 283 uchar *p; 284 struct hostent *hp; 285 286 hp = gethostbyname(host); 287 if(hp == 0) 288 return 0; 289 290 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 291 p = (uchar*)hp->h_addr_list[i]; 292 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 293 hostv[i] = strdup(buf); 294 if(hostv[i] == 0) 295 break; 296 } 297 return i; 298 } 299 300 int 301 so_gethostbyaddr(char *addr, char **hostv, int n) 302 { 303 int i; 304 struct hostent *hp; 305 unsigned long straddr; 306 307 straddr = inet_addr(addr); 308 if(straddr == -1) 309 return 0; 310 311 hp = gethostbyaddr((char *)&straddr, sizeof(straddr), AF_INET); 312 if(hp == 0) 313 return 0; 314 315 hostv[0] = strdup(hp->h_name); 316 if(hostv[0] == 0) 317 return 0; 318 for(i = 1; hp->h_aliases[i-1] && i < n; i++) { 319 hostv[i] = strdup(hp->h_aliases[i-1]); 320 if(hostv[i] == 0) 321 break; 322 } 323 return i; 324 } 325 326 int 327 so_getservbyname(char *service, char *net, char *port) 328 { 329 ushort p; 330 struct servent *s; 331 332 s = getservbyname(service, net); 333 if(s == 0) 334 return -1; 335 p = s->s_port; 336 sprint(port, "%d", nhgets(&p)); 337 return 0; 338 } 339 340 int 341 so_hangup(int fd, int nolinger) 342 { 343 int r; 344 static struct linger l = {1, 0}; 345 346 osenter(); 347 if(nolinger) 348 setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(l)); 349 r = shutdown(fd, 2); 350 if(r >= 0) 351 r = close(fd); 352 osleave(); 353 return r; 354 } 355 356 void 357 arpadd(char *ipaddr, char *eaddr, int n) 358 { 359 #ifdef SIOCGARP 360 struct arpreq a; 361 struct sockaddr_in pa; 362 int s; 363 uchar addr[IPaddrlen]; 364 365 s = socket(AF_INET, SOCK_DGRAM, 0); 366 memset(&a, 0, sizeof(a)); 367 memset(&pa, 0, sizeof(pa)); 368 pa.sin_family = AF_INET; 369 pa.sin_port = 0; 370 parseip(addr, ipaddr); 371 if(!isv4(addr)){ 372 close(s); 373 error(Ebadarg); 374 } 375 memmove(&pa.sin_addr, ipaddr+IPv4off, IPv4addrlen); 376 memmove(&a.arp_pa, &pa, sizeof(pa)); 377 while(ioctl(s, SIOCGARP, &a) != -1) { 378 ioctl(s, SIOCDARP, &a); 379 memset(&a.arp_ha, 0, sizeof(a.arp_ha)); 380 } 381 a.arp_ha.sa_family = AF_UNSPEC; 382 parsemac((uchar*)a.arp_ha.sa_data, eaddr, 6); 383 a.arp_flags = ATF_PERM; 384 if(ioctl(s, SIOCSARP, &a) == -1) { 385 oserrstr(up->env->errstr, ERRMAX); 386 close(s); 387 error(up->env->errstr); 388 } 389 close(s); 390 #else 391 error("arp not implemented"); 392 #endif 393 } 394 395 int 396 so_mustbind(int restricted, int port) 397 { 398 return restricted || port != 0; 399 } 400 401 void 402 so_keepalive(int fd, int ms) 403 { 404 int on; 405 406 on = 1; 407 setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); 408 #ifdef TCP_KEEPIDLE 409 if(ms <= 120000) 410 ms = 120000; 411 ms /= 1000; 412 setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&ms, sizeof(ms)); 413 #endif 414 } 415