1 #include <sys/types.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <netinet/tcp.h> 5 #include <netdb.h> 6 7 #include "u.h" 8 #include "lib.h" 9 #include "dat.h" 10 #include "fns.h" 11 #include "error.h" 12 13 #include "devip.h" 14 15 #undef listen 16 #undef accept 17 #undef bind 18 19 void 20 osipinit(void) 21 { 22 char buf[1024]; 23 gethostname(buf, sizeof(buf)); 24 kstrdup(&sysname, buf); 25 26 } 27 28 int 29 so_socket(int type) 30 { 31 int fd, one; 32 33 switch(type) { 34 default: 35 error("bad protocol type"); 36 case S_TCP: 37 type = SOCK_STREAM; 38 break; 39 case S_UDP: 40 type = SOCK_DGRAM; 41 break; 42 } 43 44 fd = socket(AF_INET, type, 0); 45 if(fd < 0) 46 oserror(); 47 48 one = 1; 49 if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){ 50 oserrstr(); 51 print("setsockopt: %r"); 52 } 53 54 return fd; 55 } 56 57 58 void 59 so_connect(int fd, unsigned long raddr, unsigned short rport) 60 { 61 struct sockaddr_in sin; 62 63 memset(&sin, 0, sizeof(sin)); 64 sin.sin_family = AF_INET; 65 hnputs(&sin.sin_port, rport); 66 hnputl(&sin.sin_addr.s_addr, raddr); 67 68 if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) 69 oserror(); 70 } 71 72 void 73 so_getsockname(int fd, unsigned long *laddr, unsigned short *lport) 74 { 75 socklen_t len; 76 struct sockaddr_in sin; 77 78 len = sizeof(sin); 79 if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0) 80 oserror(); 81 82 if(sin.sin_family != AF_INET || len != sizeof(sin)) 83 error("not AF_INET"); 84 85 *laddr = nhgetl(&sin.sin_addr.s_addr); 86 *lport = nhgets(&sin.sin_port); 87 } 88 89 void 90 so_listen(int fd) 91 { 92 if(listen(fd, 5) < 0) 93 oserror(); 94 } 95 96 int 97 so_accept(int fd, unsigned long *raddr, unsigned short *rport) 98 { 99 int nfd; 100 socklen_t len; 101 struct sockaddr_in sin; 102 103 len = sizeof(sin); 104 nfd = accept(fd, (struct sockaddr*)&sin, &len); 105 if(nfd < 0) 106 oserror(); 107 108 if(sin.sin_family != AF_INET || len != sizeof(sin)) 109 error("not AF_INET"); 110 111 *raddr = nhgetl(&sin.sin_addr.s_addr); 112 *rport = nhgets(&sin.sin_port); 113 return nfd; 114 } 115 116 void 117 so_bind(int fd, int su, unsigned short port) 118 { 119 int i, one; 120 struct sockaddr_in sin; 121 122 one = 1; 123 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){ 124 oserrstr(); 125 print("setsockopt: %r"); 126 } 127 128 if(su) { 129 for(i = 600; i < 1024; i++) { 130 memset(&sin, 0, sizeof(sin)); 131 sin.sin_family = AF_INET; 132 sin.sin_port = i; 133 134 if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0) 135 return; 136 } 137 oserror(); 138 } 139 140 memset(&sin, 0, sizeof(sin)); 141 sin.sin_family = AF_INET; 142 hnputs(&sin.sin_port, port); 143 144 if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0) 145 oserror(); 146 } 147 148 int 149 so_gethostbyname(char *host, char**hostv, int n) 150 { 151 int i; 152 char buf[32]; 153 unsigned char *p; 154 struct hostent *hp; 155 156 hp = gethostbyname(host); 157 if(hp == 0) 158 return 0; 159 160 for(i = 0; hp->h_addr_list[i] && i < n; i++) { 161 p = (unsigned char*)hp->h_addr_list[i]; 162 sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 163 hostv[i] = strdup(buf); 164 if(hostv[i] == 0) 165 break; 166 } 167 return i; 168 } 169 170 char* 171 hostlookup(char *host) 172 { 173 char buf[100]; 174 uchar *p; 175 struct hostent *he; 176 177 he = gethostbyname(host); 178 if(he != 0 && he->h_addr_list[0]) { 179 p = (uchar*)he->h_addr_list[0]; 180 sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]); 181 } else 182 strcpy(buf, host); 183 184 return strdup(buf); 185 } 186 187 int 188 so_getservbyname(char *service, char *net, char *port) 189 { 190 struct servent *s; 191 192 s = getservbyname(service, net); 193 if(s == 0) 194 return -1; 195 196 sprint(port, "%d", nhgets(&s->s_port)); 197 return 0; 198 } 199 200 int 201 so_send(int fd, void *d, int n, int f) 202 { 203 return send(fd, d, n, f); 204 } 205 206 int 207 so_recv(int fd, void *d, int n, int f) 208 { 209 return recv(fd, d, n, f); 210 } 211