1 /* $OpenBSD: inet_net_ntop.c,v 1.6 2005/08/06 20:30:03 espie 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 #include <sys/types.h> 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <arpa/inet.h> 24 25 #include <errno.h> 26 #include <stdio.h> 27 #include <string.h> 28 #include <stdlib.h> 29 30 static char *inet_net_ntop_ipv4(const u_char *, int, char *, size_t); 31 32 /* 33 * char * 34 * inet_net_ntop(af, src, bits, dst, size) 35 * convert network number from network to presentation format. 36 * generates CIDR style result always. 37 * return: 38 * pointer to dst, or NULL if an error occurred (check errno). 39 * author: 40 * Paul Vixie (ISC), July 1996 41 */ 42 char * 43 inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size) 44 { 45 switch (af) { 46 case AF_INET: 47 return (inet_net_ntop_ipv4(src, bits, dst, size)); 48 default: 49 errno = EAFNOSUPPORT; 50 return (NULL); 51 } 52 } 53 54 /* 55 * static char * 56 * inet_net_ntop_ipv4(src, bits, dst, size) 57 * convert IPv4 network number from network to presentation format. 58 * generates CIDR style result always. 59 * return: 60 * pointer to dst, or NULL if an error occurred (check errno). 61 * note: 62 * network byte order assumed. this means 192.5.5.240/28 has 63 * 0x11110000 in its fourth octet. 64 * author: 65 * Paul Vixie (ISC), July 1996 66 */ 67 static char * 68 inet_net_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) 69 { 70 char *odst = dst; 71 u_int m; 72 int b; 73 char *ep; 74 int advance; 75 76 ep = dst + size; 77 if (ep <= dst) 78 goto emsgsize; 79 80 if (bits < 0 || bits > 32) { 81 errno = EINVAL; 82 return (NULL); 83 } 84 if (bits == 0) { 85 if (ep - dst < sizeof "0") 86 goto emsgsize; 87 *dst++ = '0'; 88 *dst = '\0'; 89 } 90 91 /* Format whole octets. */ 92 for (b = bits / 8; b > 0; b--) { 93 if (ep - dst < sizeof "255.") 94 goto emsgsize; 95 advance = snprintf(dst, ep - dst, "%u", *src++); 96 if (advance <= 0 || advance >= ep - dst) 97 goto emsgsize; 98 dst += advance; 99 if (b > 1) { 100 if (dst + 1 >= ep) 101 goto emsgsize; 102 *dst++ = '.'; 103 *dst = '\0'; 104 } 105 } 106 107 /* Format partial octet. */ 108 b = bits % 8; 109 if (b > 0) { 110 if (ep - dst < sizeof ".255") 111 goto emsgsize; 112 if (dst != odst) 113 if (dst + 1 >= ep) 114 goto emsgsize; 115 *dst++ = '.'; 116 m = ((1 << b) - 1) << (8 - b); 117 advance = snprintf(dst, ep - dst, "%u", *src & m); 118 if (advance <= 0 || advance >= ep - dst) 119 goto emsgsize; 120 dst += advance; 121 } 122 123 /* Format CIDR /width. */ 124 if (ep - dst < sizeof "/32") 125 goto emsgsize; 126 advance = snprintf(dst, ep - dst, "/%u", bits); 127 if (advance <= 0 || advance >= ep - dst) 128 goto emsgsize; 129 dst += advance; 130 return (odst); 131 132 emsgsize: 133 errno = EMSGSIZE; 134 return (NULL); 135 } 136