28 #include <arpa/inet.h>
32 #include <sys/ioctl.h>
36 #ifdef HAVE_SYS_SOCKIO_H
37 #include <sys/sockio.h>
43 static bool running =
true;
49 registry::mapped *reg;
52 Socket::address *addr;
53 if(argc < 2 || argc > 3)
66 if(!reg->setTargets(*addr, context))
83 assert(
id != NULL && *
id != 0);
91 assert(target != NULL && *target != 0);
92 assert(buffer != NULL);
95 const char *refer = NULL;
96 linked_pointer<modules::sipwitch> cb =
getModules();
101 while(!refer && is(cb)) {
102 refer = cb->referRemote(rr, target, buffer, size);
110 assert(target != NULL && *target != 0);
111 assert(buffer != NULL);
114 const char *refer = NULL;
115 linked_pointer<modules::sipwitch> cb =
getModules();
120 while(!refer && is(cb)) {
121 refer = cb->referLocal(rr, target, buffer, size);
129 linked_pointer<modules::sipwitch> cb =
getModules();
132 if(cb->authenticate(
id, realm))
141 linked_pointer<modules::sipwitch> cb =
getModules();
144 cb->registration(
id, mode);
151 linked_pointer<modules::sipwitch> cb =
getModules();
164 linked_pointer<modules::sipwitch> cb =
getModules();
183 linked_pointer<modules::sipwitch> cb =
getModules();
186 while(!rtn && is(cb)) {
187 rtn = cb->announce(rr, msgtype, event, expires, body);
195 assert(
id != NULL && *
id != 0);
201 if(!stricmp(map->id,
id))
210 assert(
id != NULL && *
id != 0);
211 assert(node != NULL);
221 map->enlist(&
keys[path]);
229 char *
id = NULL, *secret = NULL;
231 linked_pointer<service::keynode> node;
238 const char *state =
root.getPointer();
243 const char *dirpath =
".";
261 String::set(ppd->value.id,
sizeof(ppd->value.id),
"*");
262 ppd->value.level = 1;
267 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
268 String::set(pp->value.id,
sizeof(pp->value.id),
"restricted");
274 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
275 String::set(pp->value.id,
sizeof(pp->value.id),
"local");
281 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
282 String::set(pp->value.id,
sizeof(pp->value.id),
"device");
288 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
289 String::set(pp->value.id,
sizeof(pp->value.id),
"service");
295 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
296 String::set(pp->value.id,
sizeof(pp->value.id),
"admin");
308 shell::log(
DEBUG1,
"scanning config from %s", dirpath);
309 while(is(dir) && dir.read(filename,
sizeof(filename)) > 0) {
310 ext = strrchr(filename,
'.');
311 if(!ext || !String::equal(ext,
".xml"))
314 snprintf(buf,
sizeof(buf),
"%s/%s/%s", dirpath, state, filename);
315 fp = fopen(buf,
"r");
320 snprintf(buf,
sizeof(buf),
"%s/%s", dirpath, filename);
321 fp = fopen(buf,
"r");
323 fn = strrchr(buf,
'/');
330 shell::log(shell::ERR,
"cannot load %s", fn);
332 shell::log(
DEBUG1,
"loaded %s", fn);
344 #if defined(HAVE_NET_IF_H) || defined(HAVE_PWD_H)
354 ifc.ifc_len =
sizeof(ifbuf);
356 int ifd = ::socket(AF_INET, SOCK_DGRAM, 0);
358 shell::log(shell::FAIL,
"cannot access network");
359 else if(ioctl(ifd, SIOCGIFCONF, &ifc) == -1) {
362 shell::log(shell::ERR,
"cannot list interfaces");
365 ifcount = ifc.ifc_len /
sizeof(ifreq);
367 while(index < ifcount) {
368 ifr = &ifc.ifc_req[index++];
369 if(ifr->ifr_addr.sa_family != AF_INET)
371 struct sockaddr_in *saddr = (
struct sockaddr_in *)&(ifr->ifr_addr);
372 snprintf(buf,
sizeof(buf),
"%s/", inet_ntoa(saddr->sin_addr));
373 if(ioctl(ifd, SIOCGIFNETMASK, ifr) == 0) {
374 saddr = (
struct sockaddr_in *)&(ifr->ifr_addr);
375 String::add(buf,
sizeof(buf), inet_ntoa(saddr->sin_addr));
383 node = access->getFirst();
387 if(
id && node->getPointer()) {
397 leaf = node->leaf(
"id");
400 id = leaf->getPointer();
405 if(leaf &&
id && !strcmp(node->getId(),
"profile")) {
408 memcpy(&pp->value, &ppd->value,
sizeof(
profile_t));
409 String::set(pp->value.id,
sizeof(pp->value.id),
id);
410 leaf = node->leaf(
"trs");
411 if(leaf && leaf->getPointer())
412 pp->value.level = atoi(leaf->getPointer());
413 shell::debug(2,
"adding profile %s",
id);
414 if(!stricmp(
id,
"*"))
417 else if(leaf &&
id) {
418 id = leaf->getPointer();
420 shell::log(shell::WARN,
"duplicate identity %s",
id);
421 node->setPointer((
char *)
"duplicate");
424 shell::debug(2,
"adding %s %s", node->getId(), id);
425 if(!stricmp(node->getId(),
"reject"))
428 leaf = node->leaf(
"secret");
430 secret = leaf->getPointer();
431 if(leaf && secret && *secret && !node->leaf(
"digest")) {
432 if(digest.puts((string_t)
id +
":" + (string_t)realm +
":" + (string_t)secret)) {
434 leaf =
new(mp)
keynode(node, (
char *)
"digest");
435 leaf->setPointer(dup(*digest));
439 leaf = node->leaf(
"extension");
440 if(leaf && range && leaf->getPointer())
441 number = atoi(leaf->getPointer());
442 if(number >= prefix && number < prefix + range)
443 extmap[number - prefix] = *node;
454 const char *tempname;
457 linked_pointer<keynode> temp;
461 struct group *grp = NULL;
470 if(grp && !grp->gr_mem)
474 shell::log(
DEBUG1,
"scanning users and groups");
482 leaf =
addNode(base,
"user", NULL);
483 addNode(leaf,
"id", pwd->pw_name);
485 else while(NULL != (member = grp->gr_mem[ifcount++])) {
486 leaf =
addNode(base,
"user", NULL);
493 node = base->getFirst();
496 leaf = node->leaf(
"id");
497 if(leaf && leaf->getPointer())
498 id = leaf->getPointer();
505 node->setPointer((
char *)
"invalid");
511 node->setPointer((
char *)
"duplicate");
518 cp = strchr(
id,
',');
524 if(prefix && range) {
529 if(!number && pwd->pw_uid >=
uid &&
uid > 0)
530 number = pwd->pw_uid -
uid + prefix;
532 if(number >= prefix && number < prefix + range &&
extmap[number - prefix] == NULL)
533 extmap[number - prefix] = *node;
536 snprintf(buf, 16,
"%d", number);
537 addNode(*node,
"extension", buf);
543 tempname =
"templates.user";
544 while(grp && grp->gr_mem && NULL != (member = grp->gr_mem[ifcount++])) {
545 if(String::equal(member, pwd->pw_name)) {
546 tempname =
"templates.admin";
547 entry->
reset(
"admin");
552 shell::debug(2,
"adding %s %s", node->getId(), pwd->pw_name);
560 temp = clone->getFirst();
563 copy_unsafe<keyclone>(clone, (
keyclone *)*temp);
564 clone->splice(entry);
604 assert(addr != NULL);
618 linked_pointer<stack::subnet> np = (((
server *)(
cfg))->
acl);
621 if(String::equal(np->getId(), id))
631 linked_pointer<stack::subnet> pp;
632 char buf[128], baddr[128], bmask[128];
633 struct sockaddr_storage addr, mask;
634 struct sockaddr_in *ipv4;
636 struct sockaddr_in6 *ipv6;
638 struct hostaddr_internet ha;
643 const char *
id = pp->getId();
644 int fam = pp->getFamily();
648 ipv6 = (
struct sockaddr_in6 *)&addr;
649 ha = pp->getNetwork();
650 memcpy(&ipv6->sin6_addr, &ha,
sizeof(ipv6->sin6_addr));
651 ipv6->sin6_family = AF_INET6;
652 Socket::query((
struct sockaddr *)ipv6, baddr,
sizeof(baddr));
653 ipv6 = (
struct sockaddr_in6 *)&mask;
654 ha = pp->getNetmask();
655 memcpy(&ipv6->sin6_addr, &ha,
sizeof(ipv6->sin6_addr));
656 ipv6->sin6_family = AF_INET6;
657 Socket::query((
struct sockaddr *)ipv6, bmask,
sizeof(bmask));
661 ipv4 = (
struct sockaddr_in *)&addr;
662 ha = pp->getNetwork();
663 memcpy(&ipv4->sin_addr, &ha,
sizeof(ipv4->sin_addr));
664 ipv4->sin_family = AF_INET;
665 Socket::query((
struct sockaddr *)ipv4, baddr,
sizeof(baddr));
666 ipv4 = (
struct sockaddr_in *)&mask;
667 ha = pp->getNetmask();
668 memcpy(&ipv4->sin_addr, &ha,
sizeof(ipv4->sin_addr));
669 ipv4->sin_family = AF_INET;
670 Socket::query((
struct sockaddr *)ipv4, bmask,
sizeof(bmask));
673 String::set(baddr,
sizeof(baddr),
"?");
674 String::set(bmask,
sizeof(bmask),
"?");
676 Socket::query(pp->getInterface(), buf,
sizeof(buf));
678 fprintf(fp,
"offline %s; interface=%s, %s/%s\n",
id, buf, baddr, bmask);
680 fprintf(fp,
"policy %s; interface=%s, %s/%s\n",
id, buf, baddr, bmask);
688 assert(addr != NULL);
709 linked_pointer<profile> pp;
719 if(!ppd && !stricmp(pp->value.id,
"*"))
721 if(!stricmp(pp->value.id, pro))
746 assert(cuid != NULL && *cuid != 0);
752 Socket::address *addr = NULL;
766 assert(
id != NULL && *
id != 0);
769 linked_pointer<keynode> node;
784 if(cp &&
match(
id, cp,
false))
788 if(cp && !stricmp(cp,
id))
798 assert(cuid != NULL && *cuid != 0);
809 node = cfgp->
find(cuid);
818 assert(cuid != NULL && *cuid != 0);
826 unsigned ext = atoi(cuid);
836 node = cfgp->
find(cuid);
838 leaf = node->leaf(
"extension");
843 node = cfgp->
extmap[ext - prefix];
852 assert(cuid != NULL && *cuid != 0);
859 unsigned ext = atoi(cuid);
869 node = cfgp->
find(cuid);
870 if(!node && range && ext >= prefix && ext < prefix + range)
871 node = cfgp->
extmap[ext - prefix];
879 shell::log(shell::INFO,
"checking config...");
882 shell::log(shell::INFO,
"checking components...");
884 shell::log(shell::INFO,
"checking complete");
887 shell::log(shell::WARN,
"checking failed");
896 fprintf(fp,
"Server:\n");
898 fprintf(fp,
" configure pages: %d\n",
cfg->pages());
899 fprintf(fp,
" memory paging: %ld\n", (
long)
PAGING_SIZE);
901 if(reg && reg->getFirst()) {
902 fprintf(fp,
" registry keys:\n");
906 if(reg && reg->getFirst()) {
907 fprintf(fp,
" sip stack keys:\n");
920 GetEnvironmentVariable(
"APPDATA", buf, 192);
921 unsigned len = strlen(buf);
922 snprintf(buf + len,
sizeof(buf) - len,
"\\sipwitch\\state.xml");
923 state = fopen(buf,
"r");
925 snprintf(buf,
sizeof(buf), DEFAULT_VARPATH
"/run/sipwitch/state.xml");
926 state = fopen(buf,
"r");
931 crit(cfgp != NULL,
"reload without config");
934 shell::log(
DEBUG1,
"pre-loading state configuration");
935 if(!cfgp->
load(state))
936 shell::log(shell::ERR,
"invalid state");
941 if(!cfgp->
load(fp)) {
942 shell::log(shell::ERR,
"invalid config %s",
control::env(
"config"));
947 shell::log(shell::NOTIFY,
"loaded config from %s",
control::env(
"config"));
948 cp = cfgp->
root.getPointer();
950 shell::log(shell::INFO,
"activating for state \"%s\"", cp);
958 node = cfgp->
getPath(
"access");
960 fp = fopen(_STR(
control::path(
"cache") +
"/policy.xml"),
"r");
962 if(!cfgp->
load(fp, node))
963 shell::log(shell::ERR,
"cannot load policy cache");
966 node = cfgp->
getPath(
"provision");
970 fp = fopen(_STR(
control::path(
"cache") +
"/profile.xml"),
"r");
972 if(!cfgp->
load(fp, node))
973 shell::log(shell::ERR,
"cannot load profile cache");
977 fp = fopen(_STR(
control::path(
"cache") +
"/provision.xml"),
"r");
979 if(!cfgp->
load(fp, node))
980 shell::log(shell::ERR,
"cannot load provisioning cache");
987 while(node && is(dir) && dir.read(filename,
sizeof(filename)) > 0) {
988 const char *ext = strrchr(filename,
'.');
989 if(!ext || !String::equal(ext,
".xml"))
991 if(!String::equal(filename,
"user-", 5))
993 snprintf(buf,
sizeof(buf),
"%s/%s", dirpath, filename);
994 fp = fopen(buf,
"r");
997 if(!cfgp->
load(fp, node))
998 shell::log(shell::ERR,
"cannot load user cache %s", filename);
1002 node = cfgp->
getPath(
"provider");
1004 fp = fopen(_STR(
control::path(
"cache") +
"/provider.xml"),
"r");
1006 if(!cfgp->
load(fp, node))
1007 shell::log(shell::ERR,
"cannot load provider cache");
1010 node = cfgp->
getPath(
"routing");
1012 fp = fopen(_STR(
control::path(
"cache") +
"/routing.xml"),
"r");
1014 if(!cfgp->
load(fp, node))
1015 shell::log(shell::ERR,
"cannot load routing cache");
1020 shell::log(shell::FAIL,
"no configuration");
1027 return mempool.pages();
1036 *list = (*list)->getNext();
1041 mp = mempool.alloc(size);
1043 memset(mp, 0, size);
1048 #define LIB_PREFIX "_libs"
1050 #define LIB_PREFIX ".libs"
1064 if(!list || !*list || eq(list,
"none"))
1067 if(eq(list,
"auto") || eq(list,
"all")) {
1068 String::set(path,
sizeof(path), prefix);
1071 while(is(dir) && dir.read(buffer,
sizeof(buffer)) > 0) {
1072 ep = strrchr(buffer,
'.');
1073 if(!ep || !eq(ep, MODULE_EXT))
1075 if(eq(buffer,
"lib", 3))
1077 snprintf(path + el,
sizeof(path) - el,
"/%s", buffer);
1078 shell::log(shell::INFO,
"loading %s%s", buffer, MODULE_EXT);
1079 if(fsys::load(path))
1080 shell::log(shell::ERR,
"failed loading %s", path);
1085 String::set(buffer,
sizeof(buffer), list);
1086 while(NULL != (cp = String::token(buffer, &tp,
", ;:\r\n"))) {
1087 snprintf(path,
sizeof(path),
"%s/%s%s", prefix, cp, MODULE_EXT);
1088 shell::log(shell::INFO,
"loading %s" MODULE_EXT, cp);
1089 if(fsys::load(path))
1090 shell::log(shell::ERR,
"failed loading %s", path);
1109 DateTimeString logtime;
1114 printlog(
"server starting %s\n", (
const char *)logtime);
1117 shell::debug(9,
"received request %s\n", cp);
1121 if(eq(cp,
"reload")) {
1122 printlog(
"server reloading %s\n", (
const char *)logtime);
1127 if(eq(cp,
"check")) {
1133 if(eq(cp,
"stop") || eq(cp,
"down") || eq(cp,
"exit"))
1136 if(eq(cp,
"restart")) {
1141 if(eq(cp,
"snapshot")) {
1146 if(eq(cp,
"usercache")) {
1151 if(eq(cp,
"dump")) {
1156 if(eq(cp,
"contact")) {
1159 fprintf(out,
"%s\n", *tmp);
1164 if(eq(cp,
"siplog")) {
1174 while(fgets(buf,
sizeof(buf), log) != NULL) {
1175 cp = String::strip(buf,
" \t\r\n");
1176 fprintf(out,
"%s\n", cp);
1183 if(eq(cp,
"abort")) {
1190 while(argc < 64 && NULL != (cp = const_cast<char *>(String::token(cp, &tokens,
" \t",
"{}")))) {
1197 if(eq(argv[0],
"ifup")) {
1200 printlog(
"server reloading %s\n", (
const char *)logtime);
1205 if(eq(argv[0],
"ifdown")) {
1208 printlog(
"server reloading %s\n", (
const char *)logtime);
1213 if(eq(argv[0],
"drop")) {
1219 if(eq(argv[0],
"trace")) {
1222 if(!stricmp(argv[1],
"on"))
1224 else if(!stricmp(argv[1],
"off"))
1226 else if(!stricmp(argv[1],
"clear"))
1233 if(eq(argv[0],
"uid")) {
1245 if(eq(argv[0],
"history")) {
1255 if(eq(argv[0],
"verbose")) {
1259 shell::log(
"sipwitch", (shell::loglevel_t)(atoi(argv[1])),
logmode);
continue;
1262 if(eq(argv[0],
"digest")) {
1271 if(eq(argv[0],
"realm")) {
1275 printlog(
"realm %s %s\n", argv[1], (
const char *)logtime);
1280 if(eq(argv[0],
"period")) {
1284 printlog(
"server period %s\n", (
const char *)logtime);
1288 if(eq(argv[0],
"policy") || eq(argv[0],
"network")) {
1294 struct sockaddr_storage peer;
1296 Socket::query((
struct sockaddr *)&peer, buf,
sizeof(buf));
1302 fprintf(out,
"peering as %s\n", buf);
1309 if(eq(argv[0],
"address")) {
1312 state = String::unquote(argv[1],
"\"\"\'\'()[]{}");
1314 shell::log(shell::NOTIFY,
"published address is %s", state);
1318 if(eq(argv[0],
"state")) {
1321 state = String::unquote(argv[1],
"\"\"\'\'()[]{}");
1324 fp = fopen(DEFAULT_VARPATH
"/run/sipwitch/state.def",
"w");
1329 printlog(
"state %s %s\n", state, (
const char *)logtime);
1330 shell::log(shell::NOTIFY,
"state changed to %s", state);
1336 if(eq(argv[0],
"concurrency")) {
1339 Thread::concurrency(atoi(argv[1]));
1343 if(eq(argv[0],
"message")) {
1351 if(eq(argv[0],
"activate")) {
1353 if(!activating(argc, argv,
stack::sip.out_context))
1358 if(eq(argv[0],
"release")) {
1370 printlog(
"server shutdown %s\n", (
const char *)logtime);
1375 assert(fmt != NULL && *fmt != 0);
1383 va_start(vargs, fmt);
1385 log.open(
control::env(
"logfile"), fsys::GROUP_PRIVATE, fsys::APPEND);
1386 vsnprintf(buf,
sizeof(buf) - 1, fmt, vargs);
1388 if(buf[len - 1] !=
'\n')
1392 log.write(buf, strlen(buf));
1395 cp = strchr(buf,
'\n');
1399 shell::debug(2,
"logfile: %s", buf);
linked_value< profile_t, LinkedObject > profile
static const char * sipusers
static void activate(MappedRegistry *user)
Send event for first instance of user registration.
static bool remove(const char *id)
static bool isLocal(const struct sockaddr *addr)
static void release(keynode *node)
static void userdump(void)
static String path(const char *id)
Get a string from a server environment variable.
static Socket::address * getAddress(const char *uri, Socket::address *addr=NULL)
Pointer to a provisioned user xml subtree.
User profiles are used to map features and toll restriction level together under a common identifier...
static void reply(const char *error=NULL)
Used by the server to send replies back to control requests.
static volatile dialmode_t dialmode
keynode * find(const char *id)
static const char * getInterface(void)
static keynode * getConfig(void)
#define USER_PROFILE_DEFAULT
static stack::subnet * getPolicy(const struct sockaddr *addr)
Representation of a mapped active user record.
Used to splice new chains onto an existing xml tree.
keynode * getList(const char *path)
#define USER_PROFILE_DEVICE
static unsigned getRange(void)
static void snapshot(void)
static void publish(const char *addr)
Set and publish public "appearing" address of the server.
static bool set(const char *id, const char *hash)
Linked list of named xml node locations.
static LinkedObject * getModules(void)
static bool authenticate(voip::reg_t id, const char *realm)
static void dumpfile(void)
#define USER_PROFILE_ADMIN
static void dump(FILE *fp, keynode *node, unsigned level)
static unsigned allocate(void)
static keynode * getRouting(const char *id)
bool load(FILE *file, keynode *node=NULL)
Load xml file into xml tree.
static void enableDumping(void)
bool create(const char *id, keynode *node)
static void logging(MappedRegistry *rr, const char *reason)
static const char * getRealm(void)
static condlock_t locking
static bool static char * receive(void)
Used by the server to pull pending fifo requests.
keynode * addNode(keynode *base, define *defs)
static void printlog(const char *fmt,...) __PRINTF(1
static bool isUserid(const char *id)
static void published(struct sockaddr_storage *peer)
static bool static FILE * output(const char *id)
Used to open an output session for returning control data.
static const char * referLocal(MappedRegistry *rr, const char *target, char *buffer, size_t size)
void reset(const char *tag)
static bool match(const char *digits, const char *pattern, bool partial)
static void release(stack::subnet *access)
static keynode * path(const char *p)
static unsigned short getPort(void)
static void registration(voip::reg_t id, modules::regmode_t mode)
static const char * referRemote(MappedRegistry *rr, const char *target, char *buffer, size_t size)
static bool state(const char *value)
Sets server run state configuration.
#define USER_PROFILE_SERVICE
static string_t getContact(void)
static const char * sipadmin
static shell::logmode_t logmode
static bool isExtension(const char *id)
static keynode * list(const char *p)
static void detach(mapped *m)
static stack::subnet * getSubnet(const char *id)
#define USER_PROFILE_RESTRICTED
static const char * getDigest(void)
static int system(const char *to, const char *message)
static void getProvision(const char *id, usernode &user)
static bool period(long slice)
static void disableDumping(void)
static bool checkId(const char *id)
static void clearDumping(void)
void set(shell::loglevel_t lid, const char *msg)
static void release(MappedRegistry *user)
Send event for last instance of user expired or de-registering.
System configuration instance and service functions.
#define USER_PROFILE_LOCAL
static unsigned getPrefix(void)
static void activate(MappedRegistry *rr)
static void getDialing(const char *id, usernode &user)
static void expire(MappedRegistry *rr)
static const char * getValue(keynode *base, const char *id)
static void listPolicy(FILE *fp)
static mapped * allocate(const char *id)
keynode * getPath(const char *path)
static profile_t * getProfile(const char *id)
static void plugins(const char *argv0, const char *names)
static const char * env(const char *id)
Return the value of a server environment variable.
treemap< char * > keynode
Definition of a xml node.
static bool announce(MappedRegistry *rr, const char *msgtype, const char *event, const char *expires, const char *body)