1 /******************************************************************************
2  * Copyright (c) 2004, 2008 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 
13 #include <stdint.h>
14 #include <ctype.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "args.h"
18 
19 /**
20  * Returns pointer of the n'th argument within a string.
21  *
22  * @param  arg_str    string with arguments, separated with ','
23  * @param  index      index of the requested arguments within arg_str
24  * @return            pointer of argument[index] on success
25  *                    NULL if index is out of range
26  */
27 const char *
get_arg_ptr(const char * arg_str,unsigned int index)28 get_arg_ptr(const char *arg_str, unsigned int index)
29 {
30 	unsigned int i;
31 
32 	for (i = 0; i < index; ++i) {
33 		for (; *arg_str != ',' && *arg_str != 0; ++arg_str);
34 		if (*arg_str == 0)
35 			return 0;
36 		++arg_str;
37 	}
38 	return arg_str;
39 }
40 
41 /**
42  * Returns number of arguments within a string.
43  *
44  * @param  arg_str    string with arguments, separated with ','
45  * @return            number of arguments
46  */
47 unsigned int
get_args_count(const char * arg_str)48 get_args_count(const char *arg_str)
49 {
50 	unsigned int count = 1;
51 
52 	while ((arg_str = get_arg_ptr(arg_str, 1)) != 0)
53 		++count;
54 	return count;
55 }
56 
57 /**
58  * Returns the length of the first argument.
59  *
60  * @param  arg_str    string with arguments, separated with ','
61  * @return            length of first argument
62  */
63 unsigned int
get_arg_length(const char * arg_str)64 get_arg_length(const char *arg_str)
65 {
66 	unsigned int i;
67 
68 	for (i = 0; *arg_str != ',' && *arg_str != 0; ++i)
69 		++arg_str;
70 	return i;
71 }
72 
73 /**
74  * Copy the n'th argument within a string into a buffer in respect
75  * to a limited buffer size
76  *
77  * @param  arg_str    string with arguments, separated with ','
78  * @param  index      index of the requested arguments within arg_str
79  * @param  buffer     pointer to the buffer
80  * @param  length     size of the buffer
81  * @return            pointer of buffer on success
82  *                    NULL if index is out of range.
83  */
84 char *
argncpy(const char * arg_str,unsigned int index,char * buffer,unsigned int length)85 argncpy(const char *arg_str, unsigned int index, char *buffer,
86 	unsigned int length)
87 {
88 	const char *ptr = get_arg_ptr(arg_str, index);
89 	unsigned int len;
90 
91 	if (!ptr)
92 		return 0;
93 	len = get_arg_length(ptr);
94 	if (!strncpy(buffer, ptr, length))
95 		return 0;
96 	buffer[len] = 0;
97 	return buffer;
98 }
99 
100 /**
101  * Converts "255.255.255.255\nn" -> char[4] = { 0xff, 0xff, 0xff, 0xff }
102  *                                  *netmask = subnet_netmask(nn)
103  *
104  * @param  str        string to be converted
105  * @param  ip         in case of SUCCESS - 32-bit long IP
106  *                    in case of FAULT - zero
107  * @param  netmask    return netmask if there is a valid /nn encoding in IP
108  * @return            TRUE - IP converted successfully;
109  *                    FALSE - error condition occurs (e.g. bad format)
110  */
111 int
strtoip_netmask(const char * str,char ip[4],unsigned int * netmask)112 strtoip_netmask(const char *str, char ip[4], unsigned int *netmask)
113 {
114 	char octet[10];
115 	int res;
116 	unsigned int i = 0, len, has_nn = 0;
117 
118 	while (*str != 0) {
119 		if (i > 3 || !isdigit(*str))
120 			return 0;
121 		if (strstr(str, ".") != NULL) {
122 			len = (int16_t) (strstr(str, ".") - str);
123 			if (len >= 10)
124 				return 0;
125 			strncpy(octet, str, len);
126 			octet[len] = 0;
127 			str += len;
128 		} else if (strchr(str, '\\') != NULL) {
129 			len = (short) (strchr(str, '\\') - str);
130 			if (len >= 10)
131 				return 0;
132 			strncpy(octet, str, len);
133 			octet[len] = 0;
134 			str += len;
135 			has_nn = 1;
136 		} else {
137 			strncpy(octet, str, 9);
138 			octet[9] = 0;
139 			str += strlen(octet);
140 		}
141 		res = strtol(octet, NULL, 10);
142 		if ((res > 255) || (res < 0))
143 			return 0;
144 		ip[i] = (char) res;
145 		i++;
146 		if (*str == '.')
147 			str++;
148 		if(has_nn) {
149 			str++;
150 			strncpy(octet, str, 9);
151 			octet[9] = 0;
152 			res = strtol(octet, NULL, 10);
153 			str += strlen(octet);
154 			if (res > 31 || res < 1)
155 				return 0;
156 			if (netmask)
157 				*netmask = 0xFFFFFFFF << (32 - res);
158 		}
159 	}
160 
161 	if (i != 4)
162 		return 0;
163 	return -1;
164 }
165 
166 /**
167  * Converts "255.255.255.255" -> char[4] = { 0xff, 0xff, 0xff, 0xff }
168  *
169  * @param  str        string to be converted
170  * @param  ip         in case of SUCCESS - 32-bit long IP
171  *                    in case of FAULT - zero
172  * @return            TRUE - IP converted successfully;
173  *                    FALSE - error condition occurs (e.g. bad format)
174  */
175 int
strtoip(const char * str,char ip[4])176 strtoip(const char *str, char ip[4])
177 {
178 	return strtoip_netmask(str, ip, NULL);
179 }
180