1 /* text2atm.c - Converts textual representation of ATM address to binary 2 encoding */ 3 4 /* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */ 5 6 #if HAVE_CONFIG_H 7 #include <config.h> 8 #endif 9 10 #include <stdio.h> 11 #include <ctype.h> 12 #include <string.h> 13 #include <limits.h> 14 15 #include "atm.h" 16 #include "atmsap.h" 17 #include "atmres.h" 18 19 20 static int try_pvc(const char *text,struct sockaddr_atmpvc *addr,int flags) 21 { 22 int part[3]; 23 int i; 24 25 part[0] = part[1] = part[2] = 0; 26 i = 0; 27 while (1) { 28 if (!*text) return FATAL; /* empty or ends with a dot */ 29 if (i == 3) return TRY_OTHER; /* too long */ 30 if (isdigit(*text)) { 31 if (*text == '0' && isdigit(text[1])) return TRY_OTHER; 32 /* no leading zeroes */ 33 do { 34 if (part[i] > INT_MAX/10) return TRY_OTHER;/* number too big */ 35 part[i] = part[i]*10+*text++-'0'; 36 } 37 while (isdigit(*text)); 38 i++; 39 if (!*text) break; 40 if (*text++ != '.') return TRY_OTHER; /* non-PVC character */ 41 continue; 42 } 43 if (*text == '*') { 44 if (!(flags & T2A_WILDCARD)) return FATAL; /* not allowed */ 45 part[i++] = ATM_ITF_ANY; /* all *_ANY have the same value */ 46 } 47 else { 48 if (*text != '?') return TRY_OTHER; /* invalid character */ 49 if (!(flags & T2A_UNSPEC)) return FATAL; /* not allowed */ 50 part[i++] = ATM_VPI_UNSPEC; /* all *_UNSPEC have the same 51 value */ 52 } 53 if (!*++text) break; 54 if (*text++ != '.') return FATAL; /* dot required */ 55 } 56 if (i < 2) return TRY_OTHER; /* no dots */ 57 if (i == 2) { 58 part[2] = part[1]; 59 part[1] = part[0]; 60 part[0] = 0; /* default interface */ 61 } 62 if (part[0] > SHRT_MAX || part[2] > ATM_MAX_VCI) 63 return TRY_OTHER; /* too big */ 64 if (part[1] > (flags & T2A_NNI ? ATM_MAX_VPI_NNI : ATM_MAX_VPI)) 65 return TRY_OTHER; /* too big */ 66 if (part[0] == ATM_VPI_UNSPEC) return FATAL; /* bad */ 67 addr->sap_family = AF_ATMPVC; 68 addr->sap_addr.itf = part[0]; 69 addr->sap_addr.vpi = part[1]; 70 addr->sap_addr.vci = part[2]; 71 return 0; 72 } 73 74 75 static int do_try_nsap(const char *text,struct sockaddr_atmsvc *addr,int flags) 76 { 77 const char *walk; 78 int count,pos,dot; 79 int offset,len; 80 char value; 81 82 count = dot = 0; 83 for (walk = text; *walk; walk++) 84 if (isdigit(*walk)) { 85 if (count++ == 15) break; 86 dot = 1; 87 } 88 else if (*text != '.') break; 89 else if (!dot) return FATAL; /* two dots in a row */ 90 else dot = 0; 91 if (*walk != ':') { 92 pos = 0; 93 offset = 0; 94 } 95 else { 96 if (!dot || *text == '0') return FATAL; 97 addr->sas_addr.prv[0] = ATM_AFI_E164; 98 addr->sas_addr.prv[1] = 0; 99 memset(addr->sas_addr.prv+1,0,8); 100 for (pos = 18-count-1; *text; text++) { 101 if (*text == '.') continue; 102 if (*text == ':') break; 103 else { 104 if (pos & 1) addr->sas_addr.prv[pos >> 1] |= *text-'0'; 105 else addr->sas_addr.prv[pos >> 1] = (*text-'0') << 4; 106 pos++; 107 } 108 } 109 addr->sas_addr.prv[8] |= 0xf; 110 text++; 111 pos++; 112 offset = 72; 113 } 114 for (dot = 0; *text; text++) 115 if (isxdigit(*text)) { 116 if (pos == ATM_ESA_LEN*2) return TRY_OTHER; /* too long */ 117 value = isdigit(*text) ? *text-'0' : (islower(*text) ? 118 toupper(*text) : *text)-'A'+10; 119 if (pos & 1) addr->sas_addr.prv[pos >> 1] |= value; 120 else addr->sas_addr.prv[pos >> 1] = value << 4; 121 pos++; 122 dot = 1; 123 } 124 else 125 if (*text == '/' && (flags & T2A_WILDCARD)) break; 126 else if (*text != '.') return TRY_OTHER; 127 else { 128 if (!dot) return FATAL; /* two dots in a row */ 129 dot = 0; 130 } 131 if (!dot) return FATAL; 132 if (pos > 1 && !*addr->sas_addr.prv) 133 return TRY_OTHER; /* no leading zeroes */ 134 if (!*text) 135 return pos != ATM_ESA_LEN*2 ? TRY_OTHER : ATM_ESA_LEN*2; 136 /* handle bad length */ 137 len = 0; 138 while (*++text) { 139 if (!isdigit(*text)) return -1; /* non-digit in length */ 140 if (len >= pos*4) return -1; /* too long */ 141 len = len*10+*text-'0'; 142 } 143 if (len > 7 && addr->sas_addr.prv[0] != ATM_AFI_E164) offset = 72; 144 if (len < offset) return FATAL; 145 return len > pos*4 ? TRY_OTHER : len; 146 } 147 148 149 static int try_nsap(const char *text,struct sockaddr_atmsvc *addr,int flags) 150 { 151 int result; 152 153 result = do_try_nsap(text,addr,flags); 154 if (result < 0) return result; 155 addr->sas_family = AF_ATMSVC; 156 *addr->sas_addr.pub = 0; 157 return result; 158 } 159 160 161 static int try_e164(const char *text,struct sockaddr_atmsvc *addr,int flags) 162 { 163 int i,dot,result; 164 165 if (*text == ':' || *text == '+') text++; 166 for (i = dot = 0; *text; text++) 167 if (isdigit(*text)) { 168 if (i == ATM_E164_LEN) return TRY_OTHER; /* too long */ 169 addr->sas_addr.pub[i++] = *text; 170 dot = 1; 171 } 172 else if (*text != '.') break; 173 else { 174 if (!dot) return TRY_OTHER; /* two dots in a row */ 175 dot = 0; 176 } 177 if (!dot) return TRY_OTHER; 178 addr->sas_addr.pub[i] = 0; 179 *addr->sas_addr.prv = 0; 180 result = 0; 181 if (*text) { 182 if (*text++ != '+') return TRY_OTHER; 183 else { 184 result = do_try_nsap(text,addr,flags); 185 if (result < 0) return FATAL; 186 } 187 } 188 addr->sas_family = AF_ATMSVC; 189 return result; 190 } 191 192 193 static int search(FILE *file,const char *text,struct sockaddr *addr,int length, 194 int flags) 195 { 196 char line[MAX_ATM_NAME_LEN+1]; 197 const char *here; 198 int result; 199 200 while (fgets(line,MAX_ATM_NAME_LEN,file)) { 201 if (!strtok(line,"\t\n ")) continue; 202 while ((here = strtok(NULL,"\t\n "))) 203 if (!strcasecmp(here,text)) { 204 here = strtok(line,"\t\n "); 205 result = text2atm(here,addr,length,flags); 206 if (result >= 0) return result; 207 } 208 } 209 return TRY_OTHER; 210 } 211 212 213 static int try_name(const char *text,struct sockaddr *addr,int length, 214 int flags) 215 { 216 FILE *file; 217 int result; 218 219 if (!(file = fopen(HOSTS_ATM,"r"))) return TRY_OTHER; 220 result = search(file,text,addr,length,flags); 221 (void) fclose(file); 222 return result; 223 } 224 225 226 int text2atm(const char *text,struct sockaddr *addr,int length,int flags) 227 { 228 int result; 229 230 if (!*text) return -1; 231 if (!(flags & (T2A_PVC | T2A_SVC))) flags |= T2A_PVC | T2A_SVC; 232 if (length < sizeof(struct sockaddr_atmpvc)) return -1; 233 if (flags & T2A_PVC) { 234 result = try_pvc(text,(struct sockaddr_atmpvc *) addr,flags); 235 if (result != TRY_OTHER) return result; 236 } 237 if ((flags & T2A_SVC) && length >= sizeof(struct sockaddr_atmsvc)) { 238 result = try_nsap(text,(struct sockaddr_atmsvc *) addr,flags); 239 if (result != TRY_OTHER) return result; 240 result = try_e164(text,(struct sockaddr_atmsvc *) addr,flags); 241 if (result != TRY_OTHER) return result; 242 } 243 if (!(flags & T2A_NAME)) return -1; 244 result = try_name(text,addr,length,flags & ~T2A_NAME); 245 if (result == TRY_OTHER && !(flags & T2A_LOCAL)) 246 result = ans_byname(text,(struct sockaddr_atmsvc *) addr,length,flags); 247 if (result != TRY_OTHER) return result; 248 return -1; 249 } 250