1 /* $OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $ */ 2 3 /* 4 * Copyright (c) 1996 by Internet Software Consortium. 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS 11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 12 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE 13 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 16 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 17 * SOFTWARE. 18 */ 19 20 #if defined(LIBC_SCCS) && !defined(lint) 21 #if 0 22 static const char rcsid[] = "$From: inet_net_ntop.c,v 8.2 1996/08/08 06:54:44 vixie Exp $"; 23 #else 24 static const char rcsid[] = "$OpenBSD: inet_net_ntop.c,v 1.3 2002/08/19 03:01:54 itojun Exp $"; 25 #endif 26 #endif 27 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 #include <netinet/in.h> 31 #include <arpa/inet.h> 32 33 #include <errno.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <stdlib.h> 37 38 static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t); 39 40 /* 41 * char * 42 * inet_net_ntop(af, src, bits, dst, size) 43 * convert network number from network to presentation format. 44 * generates CIDR style result always. 45 * return: 46 * pointer to dst, or NULL if an error occurred (check errno). 47 * author: 48 * Paul Vixie (ISC), July 1996 49 */ 50 char * 51 inet_net_ntop(af, src, bits, dst, size) 52 int af; 53 const void *src; 54 int bits; 55 char *dst; 56 size_t size; 57 { 58 switch (af) { 59 case AF_INET: 60 return (inet_net_ntop_ipv4(src, bits, dst, size)); 61 default: 62 errno = EAFNOSUPPORT; 63 return (NULL); 64 } 65 } 66 67 /* 68 * static char * 69 * inet_net_ntop_ipv4(src, bits, dst, size) 70 * convert IPv4 network number from network to presentation format. 71 * generates CIDR style result always. 72 * return: 73 * pointer to dst, or NULL if an error occurred (check errno). 74 * note: 75 * network byte order assumed. this means 192.5.5.240/28 has 76 * 0x11110000 in its fourth octet. 77 * author: 78 * Paul Vixie (ISC), July 1996 79 */ 80 static char * 81 inet_net_ntop_ipv4(src, bits, dst, size) 82 const u_char *src; 83 int bits; 84 char *dst; 85 size_t size; 86 { 87 char *odst = dst; 88 char *t; 89 u_int m; 90 int b; 91 char *ep; 92 int advance; 93 94 ep = dst + size; 95 if (ep <= dst) 96 goto emsgsize; 97 98 if (bits < 0 || bits > 32) { 99 errno = EINVAL; 100 return (NULL); 101 } 102 if (bits == 0) { 103 if (ep - dst < sizeof "0") 104 goto emsgsize; 105 *dst++ = '0'; 106 *dst = '\0'; 107 } 108 109 /* Format whole octets. */ 110 for (b = bits / 8; b > 0; b--) { 111 if (ep - dst < sizeof "255.") 112 goto emsgsize; 113 advance = snprintf(dst, ep - dst, "%u", *src++); 114 if (advance <= 0 || advance >= ep - dst) 115 goto emsgsize; 116 dst += advance; 117 if (b > 1) { 118 if (dst + 1 >= ep) 119 goto emsgsize; 120 *dst++ = '.'; 121 *dst = '\0'; 122 } 123 } 124 125 /* Format partial octet. */ 126 b = bits % 8; 127 if (b > 0) { 128 if (ep - dst < sizeof ".255") 129 goto emsgsize; 130 if (dst != odst) 131 if (dst + 1 >= ep) 132 goto emsgsize; 133 *dst++ = '.'; 134 m = ((1 << b) - 1) << (8 - b); 135 advance = snprintf(dst, ep - dst, "%u", *src & m); 136 if (advance <= 0 || advance >= ep - dst) 137 goto emsgsize; 138 dst += advance; 139 } 140 141 /* Format CIDR /width. */ 142 if (ep - dst < sizeof "/32") 143 goto emsgsize; 144 advance = snprintf(dst, ep - dst, "/%u", bits); 145 if (advance <= 0 || advance >= ep - dst) 146 goto emsgsize; 147 dst += advance; 148 return (odst); 149 150 emsgsize: 151 errno = EMSGSIZE; 152 return (NULL); 153 } 154