فهرست منبع

More changes for IPv6 suppot +nbname auth removed

z3APA3A 11 سال پیش
والد
کامیت
4fef3a1df0
8فایلهای تغییر یافته به همراه145 افزوده شده و 179 حذف شده
  1. 45 7
      src/3proxy.c
  2. 28 83
      src/auth.c
  3. 23 38
      src/datatypes.c
  4. 2 2
      src/ntlm.c
  5. 33 34
      src/plugins.c
  6. 0 1
      src/proxy.h
  7. 8 2
      src/structures.h
  8. 6 12
      src/webadmin.c

+ 45 - 7
src/3proxy.c

@@ -1149,6 +1149,47 @@ static int h_nolog(int argc, unsigned char **argv){
 	return 0;
 }
 
+int scanipl(unsigned char *arg, struct iplist *dst){
+#ifndef NOIPV6
+	struct sockaddr_in6 sa;
+#else
+	struct sockaddr_in sa;
+#endif
+        char * slash, *dash;
+	int masklen, addrlen;
+	if((slash = strchr(arg, '/'))) *slash = 0;
+	if((dash = strchr(arg,'-'))) *dash = 0;
+	
+	if(!getip46(46, arg, (struct sockaddr *)&sa)) return 1;
+	memcpy(&dst->ip_from, SAADDR(&sa), SAADDRLEN(&sa));
+	dst->family = *SAFAMILY(&sa);
+	if(dash){
+		if(!getip46(46, dash+1, (struct sockaddr *)&sa)) return 2;
+		memcpy(&dst->ip_to, SAADDR(&sa), SAADDRLEN(&sa));
+		return 0;
+	}
+	if(slash){
+		addrlen = SAADDRLEN(&sa);
+		masklen = atoi(slash+1);
+		if(masklen >= 0 && masklen<(addrlen*8)){
+			int i, nbytes = masklen / 8, nbits = masklen % 8;
+			
+			for(i = addrlen; i; i--){
+				((unsigned char *)&dst->ip_from)[i-1] = 0x00;
+				((unsigned char *)&dst->ip_to)[i-1] = 0xff;
+			}
+			memcpy(&dst->ip_to, &dst->ip_from, addrlen - i);
+			for(;nbits;nbits--){
+				((unsigned char *)&dst->ip_from)[i-1] &= (0x01<<(nbits-1));
+				((unsigned char *)&dst->ip_to)[i-1] |= (0x01<<(nbits-1));
+			}
+			return 0;
+		}
+	}		
+	memcpy(&dst->ip_to, &dst->ip_from, SAADDRLEN(&sa));
+	return 0;
+}
+
 struct ace * make_ace (int argc, unsigned char ** argv){
 	struct ace * acl;
 	unsigned char *arg;
@@ -1195,12 +1236,9 @@ struct ace * make_ace (int argc, unsigned char ** argv){
 					return(NULL);
 				}
 				memset(ipl, 0, sizeof(struct iplist));
-				if (!scanaddr(arg, &ipl->ip, &ipl->mask)) {
-					if((ipl->ip = getip(arg)) == 0){
-						fprintf(stderr, "Invalid IP or CIDR, line %d\n", linenum);
-						return(NULL);
-					}
-					ipl->mask = 0xFFFFFFFF;
+				if (scanipl(arg, ipl)) {
+					fprintf(stderr, "Invalid IP or CIDR, line %d\n", linenum);
+					return(NULL);
 				}
 			} while((arg = (unsigned char *)strtok((char *)NULL, ",")));
 		}
@@ -1256,7 +1294,7 @@ struct ace * make_ace (int argc, unsigned char ** argv){
 					return(NULL);
 				}
 				memset(ipl, 0, sizeof(struct iplist));
-				if (!scanaddr(arg, &ipl->ip, &ipl->mask)) {
+				if (scanipl(arg, ipl)) {
 						fprintf(stderr, "Invalid IP or CIDR, line %d\n", linenum);
 						return(NULL);
 				}

+ 28 - 83
src/auth.c

@@ -12,62 +12,6 @@
 #define HEADERSIZE 57
 #define RECORDSIZE  18
 
-unsigned char request[] = {	
-		0xa2, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x20, 0x43, 0x4b, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
-		0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 
-		0x00, 0x01};
-
-unsigned char * getNetBIOSnamebyip(unsigned long ip){
- unsigned char buf[1024];
- struct sockaddr_in sins;
- int res;
- SOCKET sock;
- unsigned char * username = NULL;
- int i;
- int j;
- int nnames;
- int type;
-
- if ( (sock=so._socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) == INVALID_SOCKET) return NULL;
- memset(&sins, 0, sizeof(sins));
- sins.sin_family = AF_INET;
- sins.sin_port = htons(0);
- sins.sin_addr.s_addr = INADDR_ANY;
- if(so._bind(sock,(struct sockaddr *)&sins,sizeof(sins))) {
-	so._closesocket(sock);
-	return NULL;
- }
- sins.sin_family = AF_INET;
- sins.sin_addr.s_addr = ip;
- sins.sin_port = htons(137);
- res=socksendto(sock, (struct sockaddr*)&sins, request, sizeof(request), conf.timeouts[SINGLEBYTE_L]*1000);
- if(res <= 0) {
-	so._closesocket(sock);
-	return NULL;
- }
- res = sockrecvfrom(sock, (struct sockaddr*)&sins, buf, sizeof(buf), conf.timeouts[SINGLEBYTE_L]*1000);
- so._closesocket(sock);
- if(res < (HEADERSIZE + RECORDSIZE)) {
-	return NULL;
- }
- nnames = buf[HEADERSIZE-1];
- if (res < (HEADERSIZE + (nnames * RECORDSIZE))) return NULL;
- for (i = 0; i < nnames; i++){
-	type = buf[HEADERSIZE + (i*RECORDSIZE) + 15];
-	if( type == 3) {
-		for(j = 14; j && buf[HEADERSIZE + (i*RECORDSIZE) + j] == ' '; j--)
-			buf[HEADERSIZE + (i*RECORDSIZE) + j] = 0;
-		if(username)myfree(username);
-		username = (unsigned char *)mystrdup((char *)buf + HEADERSIZE + i*RECORDSIZE);
-	}
-	buf[HEADERSIZE + (i*RECORDSIZE) + 15] = 0;
- }
- return username;
-} 
 
 int clientnegotiate(struct chain * redir, struct clientparam * param, unsigned long ip, unsigned short port){
 	unsigned char buf[1024];
@@ -362,6 +306,18 @@ int handleredirect(struct clientparam * param, struct ace * acentry){
 	return redir?clientnegotiate(redir, param, targetip, targetport):0;
 }
 
+int IPInentry(struct sockaddr *sa, struct iplist *ipentry){
+	int i, addrlen;
+	unsigned char *ip, *ipf, *ipt;
+	ip = (unsigned char *)SAADDR(sa);
+	ipf = (unsigned char *)&ipentry->ip_from;
+	ipt = (unsigned char *)&ipentry->ip_to;
+	if(!sa || ! ipentry || *SAFAMILY(sa) != ipentry->family) return 0;
+	addrlen = SAADDRLEN(sa);
+	for(i=0; i<addrlen; i++) if(ip[i]<ipf[i] || ip[i]>ipt[i]) return 0;
+	return 1;
+	
+}
 
 int ACLmatches(struct ace* acentry, struct clientparam * param){
 	struct userlist * userentry;
@@ -376,15 +332,14 @@ int ACLmatches(struct ace* acentry, struct clientparam * param){
 	username = param->username?param->username:(unsigned char *)"-";
 	if(acentry->src) {
 	 for(ipentry = acentry->src; ipentry; ipentry = ipentry->next)
-/* FIX IT !*/
-		if(ipentry->ip == (*(unsigned long *)SAADDR(&param->sincr) & ipentry->mask)) {
+		if(IPInentry((struct sockaddr *)&param->sincr, ipentry)) {
 			break;
 		}
-		if(!ipentry) return 0;
+	 if(!ipentry) return 0;
 	}
 	if((acentry->dst && param->req.sin_addr.s_addr) || (acentry->dstnames && param->hostname)) {
 	 for(ipentry = acentry->dst; ipentry; ipentry = ipentry->next)
-		if(ipentry->ip == (param->req.sin_addr.s_addr & ipentry->mask)) {
+		if(IPInentry((struct sockaddr *)&param->req, ipentry)) {
 			break;
 		}
 	 if(!ipentry) {
@@ -647,7 +602,11 @@ struct authcache {
 	char * username;
 	char * password;
 	time_t expires;
-	unsigned long ip;	
+#ifndef NOIPV6
+	struct sockaddr_in6 sa;
+#else
+	struct sockaddr_in sa;
+#endif
 	struct authcache *next;
 } *authc = NULL;
 
@@ -674,8 +633,7 @@ int cacheauth(struct clientparam * param){
 			
 		}
 		if(((!(conf.authcachetype&2)) || (param->username && ac->username && !strcmp(ac->username, param->username))) &&
-/* FIX IT */
-		   ((!(conf.authcachetype&1)) || ac->ip == *(unsigned long *)SAADDR(&param->sincr)) && 
+		   ((!(conf.authcachetype&1)) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa)))) && 
 		   (!(conf.authcachetype&4) || (ac->password && param->password && !strcmp(ac->password, param->password)))) {
 			if(param->username){
 				myfree(param->username);
@@ -709,8 +667,7 @@ int doauth(struct clientparam * param){
 				pthread_mutex_lock(&hash_mutex);
 				for(ac = authc; ac; ac = ac->next){
 					if((!(conf.authcachetype&2) || !strcmp(ac->username, param->username)) &&
-/* FIX IT */
-					   (!(conf.authcachetype&1) || ac->ip == *(unsigned long *)SAADDR(&param->sincr))  &&
+					   (!(conf.authcachetype&1) || (*SAFAMILY(&ac->sa) ==  *SAFAMILY(&param->sincr) && !memcmp(SAADDR(&ac->sa), &param->sincr, SAADDRLEN(&ac->sa))))  &&
 					   (!(conf.authcachetype&4) || (ac->password && !strcmp(ac->password, param->password)))) {
 						ac->expires = conf.time + conf.authcachetime;
 						if(strcmp(ac->username, param->username)){
@@ -723,8 +680,7 @@ int doauth(struct clientparam * param){
 							ac->password = mystrdup(param->password);
 							myfree(tmp);
 						}
-/* FIX IT */
-						ac->ip = *(unsigned long *)SAADDR(&param->sincr);
+						memcpy(&ac->sa, &param->sincr, SASIZE(&param->sincr));
 						break;
 					}
 				}
@@ -733,8 +689,7 @@ int doauth(struct clientparam * param){
 					if(ac){
 						ac->expires = conf.time + conf.authcachetime;
 						ac->username = mystrdup(param->username);
-/* FIX IT */
-						ac->ip = *(unsigned long *)SAADDR(&param->sincr);
+						memcpy(&ac->sa, &param->sincr, SASIZE(&param->sincr));
 						ac->password = NULL;
 						if((conf.authcachetype&4) && param->password) ac->password = mystrdup(param->password);
 					}
@@ -769,15 +724,6 @@ int userauth(struct clientparam * param){
 	return (param->username)? 0:4;
 }
 
-int nbnameauth(struct clientparam * param){
-/* FIX IT */
-	unsigned char * name = getNetBIOSnamebyip(*(unsigned long *)SAADDR(&param->sincr));
-
-	if (param->username) myfree (param->username);
-	param->username = name;
-	return name? 0:4;
-}
-
 int dnsauth(struct clientparam * param){
         char buf[32];
 /* FIX IT */
@@ -862,11 +808,10 @@ struct auth authfuncs[] = {
 	{authfuncs+1, NULL, NULL, ""},
 	{authfuncs+2, ipauth, NULL, "iponly"},
 	{authfuncs+3, userauth, checkACL, "useronly"},
-	{authfuncs+4, nbnameauth, checkACL, "nbname"},
-	{authfuncs+5, dnsauth, checkACL, "dnsname"},
-	{authfuncs+6, strongauth, checkACL, "strong"},
-	{authfuncs+7, cacheauth, checkACL, "cache"},
-	{authfuncs+8, NULL, NULL, "none"},
+	{authfuncs+4, dnsauth, checkACL, "dnsname"},
+	{authfuncs+5, strongauth, checkACL, "strong"},
+	{authfuncs+6, cacheauth, checkACL, "cache"},
+	{authfuncs+7, NULL, NULL, "none"},
 
 	{NULL, NULL, NULL, ""}
 };

+ 23 - 38
src/datatypes.c

@@ -57,19 +57,14 @@ static void pr_datetime(struct node *node, CBFUNC cbf, void*cb){
 	}
 }
 
-int ipprint(char *buf, unsigned uu){
-	unsigned u = ntohl(uu);
-
-	return sprintf(buf, "%u.%u.%u.%u", 
-		((u&0xFF000000)>>24), 
-		((u&0x00FF0000)>>16),
-		((u&0x0000FF00)>>8),
-		((u&0x000000FF)));
-}
-
 static void pr_ip(struct node *node, CBFUNC cbf, void*cb){
 	char buf[16];
-	if(node->value)(*cbf)(cb, buf, ipprint(buf, *(unsigned *)node -> value));
+	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET, node -> value, buf, 4));
+}
+
+static void pr_ip6(struct node *node, CBFUNC cbf, void*cb){
+	char buf[64];
+	if(node->value)(*cbf)(cb, buf, myinet_ntop(AF_INET6, node -> value, buf, 16));
 }
 
 static void pr_sa(struct node *node, CBFUNC cbf, void*cb){
@@ -243,9 +238,22 @@ static void pr_userlist(struct node *node, CBFUNC cbf, void*cb){
 	}
 }
 
+int printiple(char *buf, struct iplist* ipl){
+	 int addrlen = (ipl->family == AF_INET6)?16:4, i;
+	 i = myinet_ntop(ipl->family, &ipl->ip_from, buf, addrlen);
+	 if(memcmp(&ipl->ip_from, &ipl->ip_to, addrlen)){
+		buf[i++] = '-';
+		i += myinet_ntop(ipl->family, &ipl->ip_from, buf+i, addrlen);
+	 }
+	 if(ipl->next){
+		buf[i++] = ',';
+		buf[i++] = ' ';
+	}
+	return i;
+}
+
 static void pr_iplist(struct node *node, CBFUNC cbf, void*cb){
-	char buf[20];
-	int i;
+	char buf[128];
 	struct iplist *il = (struct iplist *)node->value;
 
 	if(!il) {
@@ -253,10 +261,7 @@ static void pr_iplist(struct node *node, CBFUNC cbf, void*cb){
 		return;
 	}
 	for(; il; il = il->next){
-	 i = ipprint(buf, il->ip);
-	 i += cidrprint(buf+i, il->mask);
-	 if(il->next)buf[i++] = ',';
-	 (*cbf)(cb, buf, i);
+	 (*cbf)(cb, buf, printiple(buf, il));
 	}
 }
 
@@ -277,18 +282,6 @@ static void * ef_iplist_next(struct node *node){
 	return (((struct iplist *)node->value) -> next);
 }
 
-static void * ef_iplist_ip(struct node *node){
-	return &(((struct iplist *)node->value) -> ip);
-}
-
-static void * ef_iplist_cidr(struct node *node){
-	return &(((struct iplist *)node->value) -> mask);
-}
-
-static void * ef_iplist_mask(struct node *node){
-	return &(((struct iplist *)node->value) -> mask);
-}
-
 static void * ef_userlist_next(struct node * node){
 	return (((struct userlist *)node->value) -> next);
 }
@@ -519,7 +512,6 @@ static void * ef_server_auth(struct node * node){
 	AUTHFUNC af = ((struct srvparam *)node->value) -> authfunc;
 
 	if(af == alwaysauth) return "none";
-	if(af == nbnameauth) return "nbname";
 	if(af == ipauth) return "iponly";
 	if(af == strongauth) return "strong";
 	return "uknown";
@@ -703,13 +695,6 @@ static struct property prop_pwlist[] = {
 	{NULL, "next", ef_pwlist_next, TYPE_PWLIST, "next"}
 };
 
-static struct property prop_iplist[] = {
-	{prop_iplist + 1, "ip", ef_iplist_ip, TYPE_IP, "ip address"},
-	{prop_iplist + 2, "cidr", ef_iplist_cidr, TYPE_CIDR, "ip mask length"},
-	{prop_iplist + 3, "mask", ef_iplist_mask, TYPE_IP, "ip mask"},
-	{NULL, "next", ef_iplist_next, TYPE_IPLIST, "next"}
-};
-
 static struct property prop_chain[] = {
 	{prop_chain + 1, "ip", ef_chain_ip, TYPE_IP, "parent ip address"},
 	{prop_chain + 2, "port", ef_chain_port, TYPE_PORT, "parent port"},
@@ -829,7 +814,7 @@ struct datatype datatypes[64] = {
 	{"operations", NULL, pr_operations, NULL},
 	{"rotation", NULL, pr_rotation, NULL},
 	{"portlist", ef_portlist_next, pr_portlist, prop_portlist},
-	{"iplist", ef_iplist_next, pr_iplist, prop_iplist},
+	{"iplist", ef_iplist_next, pr_iplist, NULL},
 	{"userlist", ef_userlist_next, pr_userlist, prop_userlist},
 	{"pwlist", ef_pwlist_next, NULL, prop_pwlist},
 	{"chain", ef_chain_next, NULL, prop_chain},

+ 2 - 2
src/ntlm.c

@@ -81,8 +81,8 @@ void genchallenge(struct clientparam *param, char * challenge, char *buf){
 	chal->flags[3] = 0xA0;
 	text2unicode(hostname, (char *)chal->data, 64);
 	time((time_t *)challenge);
-	memcpy(challenge+4, &param->sinc.sin_addr.s_addr, 4);
-	challenge[1]^=param->sinc.sin_port;
+	memcpy(challenge+4, SAADDR(&param->sincr), 4);
+	challenge[1]^=*SAPORT(&param->sincr);
 	for(i = 0; i < 8; i++) challenge[i] ^= myrand(challenge, 8);
 	memcpy(chal->challenge, challenge, 8);
 	en64((unsigned char *)tmpbuf, (unsigned char *)buf, (int)((unsigned char *)chal->data - (unsigned char *)chal) + len);	

+ 33 - 34
src/plugins.c

@@ -44,40 +44,39 @@ struct symbol symbols[] = {
 	{symbols+16, "trafcountfunc", (void *) trafcountfunc},
 	{symbols+17, "alwaysauth", (void *) alwaysauth},
 	{symbols+18, "ipauth", (void *) ipauth},
-	{symbols+19, "nbnameauth", (void *) nbnameauth},
-	{symbols+20, "strongauth", (void *) strongauth},
-	{symbols+21, "checkACL", (void *) checkACL},
-	{symbols+22, "nametohash", (void *) nametohash},
-	{symbols+23, "hashindex", (void *) hashindex},
-	{symbols+24, "nservers", (void *) nservers},
-	{symbols+25, "udpresolve", (void *) udpresolve},
-	{symbols+26, "bandlim_mutex", (void *) &bandlim_mutex},
-	{symbols+27, "tc_mutex", (void *) &tc_mutex},
-	{symbols+28, "hash_mutex", (void *) &hash_mutex},
-	{symbols+29, "pwl_mutex", (void *) &pwl_mutex},
-	{symbols+30, "linenum", (void *) &linenum},
-	{symbols+31, "proxy_stringtable", (void *) proxy_stringtable},
-	{symbols+32, "en64", (void *) en64},
-	{symbols+33, "de64", (void *) de64},
-	{symbols+34, "tohex", (void *) tohex},
-	{symbols+35, "fromhex", (void *) fromhex},
-	{symbols+36, "dnspr", (void *) dnsprchild},
-	{symbols+37, "pop3p", (void *) pop3pchild},
-	{symbols+38, "proxy", (void *) proxychild},
-	{symbols+39, "socks", (void *) sockschild},
-	{symbols+40, "tcppm", (void *) tcppmchild},
-	{symbols+41, "udppm", (void *) udppmchild},
-	{symbols+42, "admin", (void *) adminchild},
-	{symbols+43, "ftppr", (void *) ftpprchild},
-	{symbols+44, "smtpp", (void *) smtppchild},
-	{symbols+45, "icqpr", (void *) icqprchild},
-	{symbols+46, "msnpr", (void *) msnprchild},
-	{symbols+47, "authfuncs", (void *) &authfuncs},
-	{symbols+48, "commandhandlers", (void *) &commandhandlers},
-	{symbols+49, "decodeurl", (void *) decodeurl},
-	{symbols+50, "parsestr", (void *) parsestr},
-	{symbols+51, "make_ace", (void *) make_ace},
-	{symbols+52, "freeacl", (void *) freeacl},
+	{symbols+19, "strongauth", (void *) strongauth},
+	{symbols+20, "checkACL", (void *) checkACL},
+	{symbols+21, "nametohash", (void *) nametohash},
+	{symbols+22, "hashindex", (void *) hashindex},
+	{symbols+23, "nservers", (void *) nservers},
+	{symbols+24, "udpresolve", (void *) udpresolve},
+	{symbols+25, "bandlim_mutex", (void *) &bandlim_mutex},
+	{symbols+26, "tc_mutex", (void *) &tc_mutex},
+	{symbols+27, "hash_mutex", (void *) &hash_mutex},
+	{symbols+28, "pwl_mutex", (void *) &pwl_mutex},
+	{symbols+29, "linenum", (void *) &linenum},
+	{symbols+30, "proxy_stringtable", (void *) proxy_stringtable},
+	{symbols+31, "en64", (void *) en64},
+	{symbols+32, "de64", (void *) de64},
+	{symbols+33, "tohex", (void *) tohex},
+	{symbols+34, "fromhex", (void *) fromhex},
+	{symbols+35, "dnspr", (void *) dnsprchild},
+	{symbols+36, "pop3p", (void *) pop3pchild},
+	{symbols+37, "proxy", (void *) proxychild},
+	{symbols+38, "socks", (void *) sockschild},
+	{symbols+39, "tcppm", (void *) tcppmchild},
+	{symbols+40, "udppm", (void *) udppmchild},
+	{symbols+41, "admin", (void *) adminchild},
+	{symbols+42, "ftppr", (void *) ftpprchild},
+	{symbols+43, "smtpp", (void *) smtppchild},
+	{symbols+44, "icqpr", (void *) icqprchild},
+	{symbols+45, "msnpr", (void *) msnprchild},
+	{symbols+46, "authfuncs", (void *) &authfuncs},
+	{symbols+47, "commandhandlers", (void *) &commandhandlers},
+	{symbols+48, "decodeurl", (void *) decodeurl},
+	{symbols+49, "parsestr", (void *) parsestr},
+	{symbols+50, "make_ace", (void *) make_ace},
+	{symbols+51, "freeacl", (void *) freeacl},
 	{NULL, "", NULL}
 };
 

+ 0 - 1
src/proxy.h

@@ -174,7 +174,6 @@ int init_sql(char * s);
 void close_sql();
 #endif
 int doconnect(struct clientparam * param);
-int nbnameauth(struct clientparam * param);
 int alwaysauth(struct clientparam * param);
 int ipauth(struct clientparam * param);
 int doauth(struct clientparam * param);

+ 8 - 2
src/structures.h

@@ -170,8 +170,14 @@ struct auth {
 
 struct iplist {
 	struct iplist *next;
-	unsigned long ip;
-	unsigned long mask;
+	int family;
+#ifndef NOIPV6
+	struct in6_addr ip_from;
+	struct in6_addr ip_to;
+#else
+	struct in_addr ip_from;
+	struct in_addr ip_to;
+#endif
 };
 
 struct portlist {

+ 6 - 12
src/webadmin.c

@@ -319,21 +319,15 @@ static int printuserlist(char *buf, int bufsize, struct userlist* ul, char * del
 	return printed;
 }
 
+
+int printiple(char *buf, struct iplist* ipl);
+
 static int printiplist(char *buf, int bufsize, struct iplist* ipl, char * delim){
 	int printed = 0;
 	for(; ipl; ipl = ipl->next){
-		if(printed > (bufsize - 64)) break;
-		printed += sprintf(buf+printed, "%u.%u.%u.%u mask %u.%u.%u.%u%s",
-			(unsigned)(ntohl(ipl->ip)&0xff000000)>>24,
-			(unsigned)(ntohl(ipl->ip)&0x00ff0000)>>16,
-			(unsigned)(ntohl(ipl->ip)&0x0000ff00)>>8,
-			(unsigned)(ntohl(ipl->ip)&0x000000ff),
-			(unsigned)(ntohl(ipl->mask)&0xff000000)>>24,
-			(unsigned)(ntohl(ipl->mask)&0x00ff0000)>>16,
-			(unsigned)(ntohl(ipl->mask)&0x0000ff00)>>8,
-			(unsigned)(ntohl(ipl->mask)&0x000000ff),
-			ipl->next?delim:"");
-		if(printed > (bufsize - 64)) {
+		if(printed > (bufsize - 128)) break;
+		printed += printiple(buf+printed, ipl);
+		if(printed > (bufsize - 128)) {
 			printed += sprintf(buf+printed, "...");
 			break;
 		}