5 * ddd.ddd.ddd.ddd,nnnn IPv4 address and port
6 * ... host or port may be `*'
7 * /abs/path/to/socket AF_UNIX
8 * ./rel/path/to/socket AF_UNIX
14 #define SOCKADDR_LEN(sa) ((sa)->end - (sa)->begin)
18 int pat_sockaddr(Tcl_Interp *ip, Tcl_Obj *o, SockAddr_Value *val) {
21 rc= Tcl_ConvertToType(ip,o,&sockaddr_type);
24 *val= *OBJ_SOCKADDR(o);
28 Tcl_Obj *ret_sockaddr(Tcl_Interp *ip, SockAddr_Value val) {
32 Tcl_InvalidateStringRep(o);
33 *OBJ_SOCKADDR(o)= val;
34 o->typePtr= &sockaddr_type;
38 /* native type methods */
40 void sockaddr_clear(SockAddr_Value *v) { v->begin= v->end= 0; }
42 void sockaddr_create(SockAddr_Value *v, const struct sockaddr *addr, int len) {
45 v->begin= begin= TALLOC(len);
46 memcpy(begin, addr, len);
50 int sockaddr_len(const SockAddr_Value *v) {
51 return SOCKADDR_LEN(v);
54 const struct sockaddr *sockaddr_addr(const SockAddr_Value *v) {
55 return (const void*)v->begin;
58 void sockaddr_free(const SockAddr_Value *v) {
62 /* Sockaddr Tcl type */
64 static void sockaddr_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
66 sockaddr_create(OBJ_SOCKADDR(dup),
67 sockaddr_addr(OBJ_SOCKADDR(src)),
68 sockaddr_len(OBJ_SOCKADDR(src)));
71 static void sockaddr_t_free(Tcl_Obj *o) {
72 sockaddr_free(OBJ_SOCKADDR(o));
75 static void sockaddr_t_ustr(Tcl_Obj *o) {
76 const struct sockaddr *sa;
77 char i46buf[INET6_ADDRSTRLEN], portbuf[50];
78 const struct sockaddr_in *sin;
80 const char *string, *prepend;
82 sa= sockaddr_addr(OBJ_SOCKADDR(o));
83 al= sockaddr_len(OBJ_SOCKADDR(o));
85 switch (sa->sa_family) {
88 assert(sizeof(i46buf) >= INET_ADDRSTRLEN);
89 assert(al >= sizeof(struct sockaddr_in));
91 inet_ntop(sa->sa_family, &sin->sin_addr, i46buf, al);
92 snprintf(portbuf,sizeof(portbuf),",%d",(int)ntohs(sin->sin_port));
98 string= ((const struct sockaddr_un*)sa)->sun_path;
100 if (!string[0]) string="//";
101 else if (string[0] != '/' || string[1] == '/') prepend= "./";
104 default: /* ouch ! */
105 obj_updatestr_array_prefix(o,(const void*)sa,al,"?");
109 obj_updatestr_vstringls(o,
110 prepend, strlen(prepend),
111 string, strlen(string),
115 static int sockaddr_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
117 struct sockaddr_un sun;
118 struct sockaddr_in sin;
120 unsigned long port_l;
122 char *str, *ep, *copy;
124 const char *comma, *path;
126 str= Tcl_GetStringFromObj(o,0); assert(str);
128 memset(&s,0,sizeof(s));
130 if (str[0]=='/' || (str[0]=='.' && str[1]=='/')) {
133 s.sun.sun_family= AF_UNIX;
135 if (!strcmp(str,"//")) path= "";
136 else if (!memcmp(str,"./",2) && str[2]) path= str+2;
137 else { assert(str[0]=='/' && str[1]!='/'); path=str; }
139 if (strlen(str) >= sizeof(s.sun.sun_path))
140 return staticerr(ip, "AF_UNIX path too long");
142 strcpy(s.sun.sun_path, path);
144 } else if ((comma= strchr(str, ','))) {
147 s.sin.sin_family= AF_INET;
151 memcpy(copy, str, pl);
154 if (!strcmp(copy,"*")) {
155 s.sin.sin_addr.s_addr= INADDR_ANY;
158 iprv= inet_pton(AF_INET, copy, &s.sin.sin_addr);
162 if (!iprv) return staticerr(ip, "bad IPv4 address syntax");
165 if (!strcmp(comma,"*")) {
168 errno=0; port_l=strtoul(comma,&ep,10);
169 if (errno || *ep) return staticerr(ip, "bad IPv4 port");
170 if (port_l > 65535) return staticerr(ip, "IPv4 port out of range");
171 s.sin.sin_port= htons(port_l);
176 return staticerr(ip, "bad socket address syntax");
180 sockaddr_create(OBJ_SOCKADDR(o), (void*)&s, sl);
182 o->typePtr = &sockaddr_type;
186 Tcl_ObjType sockaddr_type = {
188 sockaddr_t_free, sockaddr_t_dup, sockaddr_t_ustr, sockaddr_t_sfa