📄 ans.c
字号:
/* ans.c - Interface for text2atm and atm2text to ANS *//* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA *//* * This stuff is a temporary hack to avoid using gethostbyname_nsap and such * without doing the "full upgrade" to getaddrinfo/getnameinfo. This also * serves as an exercise for me to get all the details right before I propose * a patch that would eventually end up in libc (and that should therefore be * as stable as possible). */#if HAVE_CONFIG_H#include <config.h>#endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <netinet/in.h>#include <arpa/nameser.h>#include <netdb.h>#include <resolv.h>#include "atm.h"#include "atmres.h"#define MAX_ANSWER 2048#define MAX_NAME 1024#define MAX_LINE 2048 /* in /etc/e164_cc */#define E164_CC_DEFAULT_LEN 2#define E164_CC_FILE "/etc/e164_cc"#define GET16(pos) (((pos)[0] << 8) | (pos)[1])static int ans(const char *text,int wanted,void *result,int res_len){ unsigned char answer[MAX_ANSWER]; unsigned char name[MAX_NAME]; unsigned char *pos,*data,*found; int answer_len,name_len,data_len,found_len; int questions,answers; found_len = 0; /* gcc wants it */ if ((answer_len = res_search(text,C_IN,wanted,answer,MAX_ANSWER)) < 0) return TRY_OTHER; /* * Response header: id, flags, #queries, #answers, #authority, * #additional (all 16 bits) */ pos = answer+12; if (answer[3] & 15) return TRY_OTHER; /* rcode != 0 */ questions = GET16(answer+4); if (questions != 1) return TRY_OTHER; /* trouble ... */ answers = GET16(answer+6); if (answers < 1) return TRY_OTHER; /* * Query: name, type (16), class (16) */ if ((name_len = dn_expand(answer,answer+answer_len,pos,name,MAX_NAME)) < 0) return TRY_OTHER; pos += name_len; if (GET16(pos) != wanted || GET16(pos+2) != C_IN) return TRY_OTHER; pos += 4; /* * Iterate over answers until we find something we like, giving priority * to ATMA_AESA (until signaling is fixed to work with E.164 too) */ found = NULL; while (answers--) { /* * RR: name, type (16), class (16), TTL (32), resource_len (16), * resource_data ... */ if ((name_len = dn_expand(answer,answer+answer_len,pos,name,MAX_NAME)) < 0) return TRY_OTHER; pos += name_len; data_len = GET16(pos+8); data = pos+10; pos = data+data_len; if (GET16(data-10) != wanted || GET16(data-8) != C_IN || !--data_len) continue; switch (wanted) { case T_NSAP: data_len++; if (data_len != ATM_ESA_LEN) continue; memcpy(((struct sockaddr_atmsvc *) result)-> sas_addr.prv,data,ATM_ESA_LEN); return 0; case T_ATMA: switch (*data++) { case ATMA_AESA: if (data_len != ATM_ESA_LEN) continue; memcpy(((struct sockaddr_atmsvc *) result)-> sas_addr.prv,data,ATM_ESA_LEN); return 0; case ATMA_E164: if (data_len > ATM_E164_LEN) continue; if (!found) { found = data; found_len = data_len; } break; default: continue; } case T_PTR: if (dn_expand(answer,answer+answer_len,data,result, res_len) < 0) return FATAL; return 0; default: continue; } } if (!found) return TRY_OTHER; memcpy(((struct sockaddr_atmsvc *) result)->sas_addr.pub,found, found_len); ((struct sockaddr_atmsvc *) result)->sas_addr.pub[found_len] = 0; return 0;}int ans_byname(const char *text,struct sockaddr_atmsvc *addr,int length, int flags){ if (!(flags & T2A_SVC) || length != sizeof(*addr)) return TRY_OTHER; memset(addr,0,sizeof(*addr)); addr->sas_family = AF_ATMSVC; if (!ans(text,T_ATMA,addr,length)) return 0; return ans(text,T_NSAP,addr,length);}static int encode_nsap(char *buf,const unsigned char *addr){ static int fmt_dcc[] = { 2,12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 4,2,0 }; static int fmt_e164[] = { 2,12,1,1,1,1,1,1,1,1,16,2,0 }; int *fmt; int pos,i,j; switch (*addr) { case ATM_AFI_DCC: case ATM_AFI_ICD: case ATM_AFI_LOCAL: case ATM_AFI_DCC_GROUP: case ATM_AFI_ICD_GROUP: case ATM_AFI_LOCAL_GROUP: fmt = fmt_dcc; break; case ATM_AFI_E164: case ATM_AFI_E164_GROUP: fmt = fmt_e164; break; default: return TRY_OTHER; } pos = 2*ATM_ESA_LEN; for (i = 0; fmt[i]; i++) { pos -= fmt[i]; for (j = 0; j < fmt[i]; j++) sprintf(buf++,"%x", (addr[(pos+j) >> 1] >> 4*(1-((pos+j) & 1))) & 0xf); *buf++ = '.'; } strcpy(buf,"AESA.ATMA.INT."); return 0;}static int encode_nsap_new(char *buf,const unsigned char *addr){ int i; int digit; for (i = 20; i; ) { i--; digit = addr[i] & 0x0F; *(buf++) = digit + (digit >= 10 ? '7' : '0'); *(buf++) = '.'; digit = ((unsigned char) (addr[i])) >> 4; *(buf++) = digit + (digit >= 10 ? '7' : '0'); *(buf++) = '.'; } strcpy (buf, "NSAP.INT."); return 0;}static int cc_len(int p0,int p1){ static char *cc_table = NULL; FILE *file; char buffer[MAX_LINE]; char *here; int cc; if (!cc_table) { if (!(cc_table = malloc(100))) { perror("malloc"); return E164_CC_DEFAULT_LEN; } memset(cc_table,E164_CC_DEFAULT_LEN,100); if (!(file = fopen(E164_CC_FILE,"r"))) perror(E164_CC_FILE); else { while (fgets(buffer,MAX_LINE,file)) { here = strchr(buffer,'#'); if (here) *here = 0; if (sscanf(buffer,"%d",&cc) == 1) { if (cc < 10) cc_table[cc] = 1; else if (cc < 100) cc_table[cc] = 2; else cc_table[cc/10] = 3; } } fclose(file); } } if (cc_table[p0] == 1) return 1; return cc_table[p0*10+p1];}static int encode_e164(char *buf,const char *addr){ const char *prefix,*here; prefix = addr+cc_len(addr[0]-48,addr[1]-48); here = strchr(addr,0); while (here > prefix) { *buf++ = *--here; *buf++ = '.'; } while (here > addr) *buf++ = *addr++; strcpy(buf,".E164.ATMA.INT."); return 0;}int ans_byaddr(char *buffer,int length,const struct sockaddr_atmsvc *addr, int flags){ char tmp[MAX_NAME]; /* could be smaller ... */ int res; if (addr->sas_addr.prv) { res = encode_nsap(tmp,addr->sas_addr.prv); if (!res && !ans(tmp,T_PTR,buffer,length)) return 0; res = encode_nsap_new(tmp,addr->sas_addr.prv); if (res < 0) return res; return ans(tmp,T_PTR,buffer,length); } else { res = encode_e164(tmp,addr->sas_addr.pub); if (res < 0) return res; return ans(tmp,T_PTR,buffer,length); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -