![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_objects.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2006, Digium, Inc. 00005 * and Edvina AB, Sollentuna, Sweden (chan_sip3 changes/additions) 00006 * 00007 * Mark Spencer <markster@digium.com> 00008 * 00009 * See http://www.asterisk.org for more information about 00010 * the Asterisk project. Please do not directly contact 00011 * any of the maintainers of this project for assistance; 00012 * the project provides a web site, mailing lists and IRC 00013 * channels for your use. 00014 * 00015 * This program is free software, distributed under the terms of 00016 * the GNU General Public License Version 2. See the LICENSE file 00017 * at the top of the source tree. 00018 */ 00019 00020 /*! 00021 * \file 00022 * \brief Various SIP object handling functions 00023 * (phones, trunks, services) 00024 * Version 3 of chan_sip 00025 * 00026 * \author Mark Spencer <markster@digium.com> 00027 * \author Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes) 00028 * 00029 * See Also: 00030 * \arg \ref AstCREDITS 00031 * 00032 */ 00033 00034 #include "asterisk.h" 00035 00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 53128 $") 00037 00038 #include <stdio.h> 00039 #include <ctype.h> 00040 #include <string.h> 00041 #include <unistd.h> 00042 #include <sys/socket.h> 00043 #include <sys/ioctl.h> 00044 #include <net/if.h> 00045 #include <errno.h> 00046 #include <stdlib.h> 00047 #include <fcntl.h> 00048 #include <netdb.h> 00049 #include <signal.h> 00050 #include <sys/signal.h> 00051 #include <netinet/in.h> 00052 #include <netinet/in_systm.h> 00053 #include <arpa/inet.h> 00054 #include <netinet/ip.h> 00055 #include <regex.h> 00056 00057 #include "asterisk/lock.h" 00058 #include "asterisk/channel.h" 00059 #include "asterisk/config.h" 00060 #include "asterisk/logger.h" 00061 #include "asterisk/module.h" 00062 #include "asterisk/pbx.h" 00063 #include "asterisk/options.h" 00064 #include "asterisk/sched.h" 00065 #include "asterisk/io.h" 00066 #include "asterisk/rtp.h" 00067 #include "asterisk/udptl.h" 00068 #include "asterisk/acl.h" 00069 #include "asterisk/manager.h" 00070 #include "asterisk/callerid.h" 00071 #include "asterisk/cli.h" 00072 #include "asterisk/app.h" 00073 #include "asterisk/musiconhold.h" 00074 #include "asterisk/dsp.h" 00075 #include "asterisk/features.h" 00076 #include "asterisk/srv.h" 00077 #include "asterisk/astdb.h" 00078 #include "asterisk/causes.h" 00079 #include "asterisk/utils.h" 00080 #include "asterisk/file.h" 00081 #include "asterisk/astobj.h" 00082 #include "asterisk/dnsmgr.h" 00083 #include "asterisk/devicestate.h" 00084 #include "asterisk/linkedlists.h" 00085 #include "asterisk/stringfields.h" 00086 #include "asterisk/monitor.h" 00087 #include "asterisk/localtime.h" 00088 #include "asterisk/abstract_jb.h" 00089 #include "asterisk/compiler.h" 00090 #include "sip3.h" 00091 #include "sip3funcs.h" 00092 00093 00094 struct sip_device_list devicelist; /*!< The device list */ 00095 00096 /*! \brief Support routine for find_device */ 00097 static int sip_addrcmp(char *name, struct sockaddr_in *sin) 00098 { 00099 /* We know name is the first field, so we can cast */ 00100 struct sip_device *peer = (struct sip_device *) name; 00101 return !(!inaddrcmp(&peer->addr, sin) || 00102 (ast_test_flag(&peer->flags[0], SIP_INSECURE_PORT) && 00103 (peer->addr.sin_addr.s_addr == sin->sin_addr.s_addr))); 00104 } 00105 00106 00107 /*! \brief Update peer object in realtime storage 00108 If the Asterisk system name is set in asterisk.conf, we will use 00109 that name and store that in the "regserver" field in the sippeers 00110 table to facilitate multi-server setups. 00111 */ 00112 GNURK void realtime_update_peer(const char *peername, struct sockaddr_in *sin, const char *username, const char *fullcontact, int expiry) 00113 { 00114 char port[10]; 00115 char ipaddr[INET_ADDRSTRLEN]; 00116 char regseconds[20]; 00117 00118 char *sysname = ast_config_AST_SYSTEM_NAME; 00119 char *syslabel = NULL; 00120 00121 time_t nowtime = time(NULL) + expiry; 00122 const char *fc = fullcontact ? "fullcontact" : NULL; 00123 00124 snprintf(regseconds, sizeof(regseconds), "%d", (int)nowtime); /* Expiration time */ 00125 ast_copy_string(ipaddr, ast_inet_ntoa(sin->sin_addr), sizeof(ipaddr)); 00126 snprintf(port, sizeof(port), "%d", ntohs(sin->sin_port)); 00127 00128 if (ast_strlen_zero(sysname)) /* No system name, disable this */ 00129 sysname = NULL; 00130 else if (ast_test_flag(&global.flags[1], SIP_PAGE2_RTSAVE_SYSNAME)) 00131 syslabel = "regserver"; 00132 00133 if (fc) 00134 ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, 00135 "port", port, "regseconds", regseconds, 00136 "defaultuser", username, fc, fullcontact, syslabel, sysname, NULL); /* note fc and syslabel _can_ be NULL */ 00137 else 00138 ast_update_realtime("sippeers", "name", peername, "ipaddr", ipaddr, 00139 "port", port, "regseconds", regseconds, 00140 "defaultuser", username, syslabel, sysname, NULL); /* note syslabel _can_ be NULL */ 00141 } 00142 00143 /*! \brief Automatically add peer extension to dial plan */ 00144 GNURK void register_peer_exten(struct sip_device *device, int onoff) 00145 { 00146 char multi[256]; 00147 char *stringp, *ext, *context; 00148 00149 /* XXX note that global.regcontext is both a global 'enable' flag and 00150 * the name of the global regexten context, if not specified 00151 * individually. 00152 */ 00153 if (ast_strlen_zero(global.regcontext)) 00154 return; 00155 00156 ast_copy_string(multi, S_OR(device->extra.regexten, device->name), sizeof(multi)); 00157 stringp = multi; 00158 while ((ext = strsep(&stringp, "&"))) { 00159 if ((context = strchr(ext, '@'))) { 00160 *context++ = '\0'; /* split ext@context */ 00161 if (!ast_context_find(context)) { 00162 ast_log(LOG_WARNING, "Context %s must exist in regcontext= in sip.conf!\n", context); 00163 continue; 00164 } 00165 } else { 00166 context = global.regcontext; 00167 } 00168 if (onoff) 00169 ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop", 00170 ast_strdup(device->name), ast_free, "SIP"); 00171 else 00172 ast_context_remove_extension(context, ext, 1, NULL); 00173 } 00174 } 00175 00176 /*! \brief Destroy device object from memory */ 00177 GNURK void sip_destroy_device(struct sip_device *device) 00178 { 00179 logdebug(3, "Destroying SIP device %s\n", device->name); 00180 //if (option_debug > 2) 00181 //ast_log(LOG_DEBUG, "Destroying SIP %s %s\n", device->type & SIP_USER ? "user" : "peer", device->name); 00182 00183 /* Delete it, it needs to disappear */ 00184 if (device->call) 00185 sip_destroy(device->call); 00186 if (device->chanvars) { 00187 ast_variables_destroy(device->chanvars); 00188 device->chanvars = NULL; 00189 } 00190 00191 if (device->mailbox.mwipvt) /* We have an active subscription, delete it */ 00192 sip_destroy(device->mailbox.mwipvt); 00193 00194 if (device->expire > -1) 00195 ast_sched_del(sched, device->expire); 00196 if (device->pokeexpire > -1) 00197 ast_sched_del(sched, device->pokeexpire); 00198 ast_free_ha(device->ha); 00199 00200 if (device->type & SIP_PEER) { 00201 register_peer_exten(device, FALSE); 00202 clear_realm_authentication(device->auth); 00203 device->auth = (struct sip_auth *) NULL; 00204 if (ast_test_flag((&device->flags[1]), SIP_PAGE2_SELFDESTRUCT)) 00205 sipcounters.autocreated_peers--; 00206 else if (ast_test_flag(&device->flags[0], SIP_REALTIME)) 00207 sipcounters.realtime_peers--; 00208 else 00209 sipcounters.static_peers--; 00210 } 00211 if (device->type & SIP_USER) { /* SIP_USER */ 00212 if (ast_test_flag(&device->flags[0], SIP_REALTIME)) 00213 sipcounters.realtime_users--; 00214 else 00215 sipcounters.static_users--; 00216 } 00217 if (device->dnsmgr) 00218 ast_dnsmgr_release(device->dnsmgr); 00219 if (device->registry) { 00220 device->registry->peer = NULL; 00221 ASTOBJ_UNREF(device->registry,sip_registry_destroy); 00222 } 00223 00224 /* Free the stringfield pool */ 00225 ast_string_field_free_pools(device); 00226 free(device); 00227 } 00228 00229 /*! \brief Update peer data in database (if used) */ 00230 GNURK void update_peer(struct sip_device *device, int expiry) 00231 { 00232 int rtcachefriends = ast_test_flag(&device->flags[1], SIP_PAGE2_RTCACHEFRIENDS); 00233 if (ast_test_flag(&global.flags[1], SIP_PAGE2_RTUPDATE) && 00234 (ast_test_flag(&device->flags[0], SIP_REALTIME) || rtcachefriends)) { 00235 realtime_update_peer(device->name, &device->addr, device->defaultuser, rtcachefriends ? device->fullcontact : NULL, expiry); 00236 } 00237 } 00238 00239 /*! \brief Locate peer by name or ip address 00240 * This is used on incoming SIP message to find matching peer on ip 00241 or outgoing message to find matching peer on name */ 00242 GNURK struct sip_device *find_device(const char *device, struct sockaddr_in *sin, int realtime) 00243 { 00244 struct sip_device *peer = NULL; 00245 00246 if (device) 00247 peer = ASTOBJ_CONTAINER_FIND(&devicelist, device); 00248 else 00249 peer = ASTOBJ_CONTAINER_FIND_FULL(&devicelist, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); 00250 00251 if (!peer && realtime) 00252 peer = realtime_peer(device, sin); 00253 00254 return peer; 00255 } 00256 00257 /*! \brief Create temporary peer (used in autocreatepeer mode) */ 00258 GNURK struct sip_device *temp_device(const char *name) 00259 { 00260 struct sip_device *peer; 00261 00262 if (!(peer = ast_calloc(1, sizeof(*peer)))) 00263 return NULL; 00264 00265 sipcounters.autocreated_peers++; 00266 ASTOBJ_INIT(peer); 00267 peer->type = SIP_PEER; 00268 set_device_defaults(peer); 00269 00270 ast_copy_string(peer->name, name, sizeof(peer->name)); 00271 00272 ast_set_flag(&peer->flags[1], SIP_PAGE2_SELFDESTRUCT); 00273 ast_set_flag(&peer->flags[1], SIP_PAGE2_DYNAMIC); 00274 peer->prefs = global.default_prefs; 00275 reg_source_db(peer); 00276 00277 return peer; 00278 } 00279 00280 /*! \brief Get registration details from Asterisk DB 00281 \ref chan_sip3_registrydb 00282 */ 00283 GNURK void reg_source_db(struct sip_device *peer) 00284 { 00285 /*! \page chan_sip3_registrydb SIP3 :: THe registry database (astdb) 00286 The SIP3 registry database contains a string that contains 00287 fields separated by | characters. When a device registers, 00288 the string is stored to the database in order to allow 00289 restarts of Asterisk without loosing data. 00290 When Asterisk restarts, the SIP channel loads data from 00291 the ASTDB "sip3-registry" family in order to populate 00292 the peer list with registered peers. 00293 00294 \b Fields: 00295 00296 - \b Expirytime: The time (unix time) when this registration expires 00297 - \b IP address: Registered IP address or NAT address 00298 - \b Port: Registered port our NAT port 00299 - \b Expiry: How long this registration is valid 00300 - \b Contact: The Contact header registered with Asterisk 00301 00302 \b Functions: 00303 00304 - \ref reg_source_db() 00305 00306 A problem with this is that if Asterisk has not been running for more 00307 than 30 secs, we might not be able to keep NAT relations alive and will 00308 send out keepalives that will be refused by the NAT. The device will 00309 quickly become UNREACHABLE until we get a new registration from the inside. 00310 */ 00311 00312 char data[BUFSIZ * 4]; 00313 struct in_addr in; 00314 int expiry; 00315 int port; 00316 time_t exptime; 00317 char *scan, *expirytime, *addr, *port_str, *expiry_str, *contact; 00318 00319 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_RT_FROMCONTACT)) /*! \bug XXX What is this???? */ 00320 return; 00321 if (ast_db_get("SIP3-Registry", peer->name, data, sizeof(data))) 00322 return; 00323 00324 scan = data; 00325 expirytime = strsep(&scan, "|"); 00326 addr = strsep(&scan, "|"); 00327 port_str = strsep(&scan, "|"); 00328 expiry_str = strsep(&scan, "|"); 00329 contact = scan; /* Contact include sip: and has to be the last part of the database entry as long as we use : as a separator */ 00330 00331 exptime = (time_t) atoi(expirytime); 00332 if (exptime < time(NULL)) { 00333 /* This peer as expired, registration no longer valid */ 00334 if (option_debug > 1 && sipdebug) 00335 ast_log(LOG_DEBUG, "Peer %s has expired. Deleting entry in astdb\n", peer->name); 00336 ast_db_del("SIP3-Registry", peer->name); 00337 return; 00338 } 00339 if (!inet_aton(addr, &in)) 00340 return; 00341 00342 if (port_str) 00343 port = atoi(port_str); 00344 else 00345 return; 00346 00347 if (expiry_str) 00348 expiry = atoi(expiry_str); 00349 else 00350 return; 00351 00352 if (contact) 00353 ast_string_field_set(peer, fullcontact, contact); 00354 00355 if (option_verbose > 2) 00356 ast_verbose(VERBOSE_PREFIX_3 "SIP Loaded device from astdb: '%s' at %s:%d for %d\n", 00357 peer->name, ast_inet_ntoa(in), port, expiry); 00358 00359 memset(&peer->addr, 0, sizeof(peer->addr)); 00360 peer->addr.sin_family = AF_INET; 00361 peer->addr.sin_addr = in; 00362 peer->addr.sin_port = htons(port); 00363 00364 /* Schedule a poke only, pretty soon */ 00365 if (peer->pokeexpire > -1) 00366 ast_sched_del(sched, peer->pokeexpire); 00367 peer->pokeexpire = ast_sched_add(sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer); 00368 00369 if (peer->expire > -1) 00370 ast_sched_del(sched, peer->expire); 00371 00372 00373 //peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer); 00374 peer->expire = ast_sched_add(sched, (exptime + 10 - time(NULL)) * 1000, expire_register, peer); 00375 00376 register_peer_exten(peer, TRUE); 00377 } 00378 00379 /*! \brief Remove registration data from realtime database or AST/DB when registration expires */ 00380 GNURK void destroy_association(struct sip_device *device) 00381 { 00382 if (!ast_test_flag(&global.flags[1], SIP_PAGE2_IGNOREREGEXPIRE)) { 00383 if (ast_test_flag(&device->flags[1], SIP_PAGE2_RT_FROMCONTACT)) 00384 ast_update_realtime("sippeers", "name", device->name, "fullcontact", "", "ipaddr", "", "port", "", "regseconds", "0", "defaultuser", "", "regserver", "", NULL); 00385 else 00386 ast_db_del("SIP3-Registry", device->name); 00387 } 00388 } 00389 00390 /*! \brief Expire registration of SIP device */ 00391 GNURK int expire_register(void *data) 00392 { 00393 struct sip_device *device = data; 00394 00395 if (!device) /* Hmmm. We have no peer. Weird. */ 00396 return 0; 00397 00398 memset(&device->addr, 0, sizeof(device->addr)); 00399 00400 destroy_association(device); /* remove registration data from storage */ 00401 00402 manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", device->name); 00403 register_peer_exten(device, FALSE); /* Remove regexten */ 00404 device->expire = -1; 00405 ast_device_state_changed("SIP/%s", device->name); 00406 00407 /* Do we need to release this peer from memory? 00408 Only for realtime peers and autocreated peers 00409 */ 00410 if (ast_test_flag(&device->flags[1], SIP_PAGE2_SELFDESTRUCT) || 00411 ast_test_flag(&device->flags[1], SIP_PAGE2_RTAUTOCLEAR)) { 00412 device = ASTOBJ_CONTAINER_UNLINK(&devicelist, device); /* Remove from peer list */ 00413 device_unref(device); 00414 } 00415 00416 return 0; 00417 }