Annotation of embedaddon/nginx/src/http/modules/ngx_http_realip_module.c, revision 1.1

1.1     ! misho       1: 
        !             2: /*
        !             3:  * Copyright (C) Igor Sysoev
        !             4:  * Copyright (C) Nginx, Inc.
        !             5:  */
        !             6: 
        !             7: 
        !             8: #include <ngx_config.h>
        !             9: #include <ngx_core.h>
        !            10: #include <ngx_http.h>
        !            11: 
        !            12: 
        !            13: #define NGX_HTTP_REALIP_XREALIP  0
        !            14: #define NGX_HTTP_REALIP_XFWD     1
        !            15: #define NGX_HTTP_REALIP_HEADER   2
        !            16: 
        !            17: 
        !            18: typedef struct {
        !            19:     ngx_array_t       *from;     /* array of ngx_cidr_t */
        !            20:     ngx_uint_t         type;
        !            21:     ngx_uint_t         hash;
        !            22:     ngx_str_t          header;
        !            23:     ngx_flag_t         recursive;
        !            24: } ngx_http_realip_loc_conf_t;
        !            25: 
        !            26: 
        !            27: typedef struct {
        !            28:     ngx_connection_t  *connection;
        !            29:     struct sockaddr   *sockaddr;
        !            30:     socklen_t          socklen;
        !            31:     ngx_str_t          addr_text;
        !            32: } ngx_http_realip_ctx_t;
        !            33: 
        !            34: 
        !            35: static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
        !            36: static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
        !            37:     ngx_addr_t *addr);
        !            38: static void ngx_http_realip_cleanup(void *data);
        !            39: static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
        !            40:     void *conf);
        !            41: static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
        !            42: static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf);
        !            43: static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf,
        !            44:     void *parent, void *child);
        !            45: static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf);
        !            46: 
        !            47: 
        !            48: static ngx_command_t  ngx_http_realip_commands[] = {
        !            49: 
        !            50:     { ngx_string("set_real_ip_from"),
        !            51:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            52:       ngx_http_realip_from,
        !            53:       NGX_HTTP_LOC_CONF_OFFSET,
        !            54:       0,
        !            55:       NULL },
        !            56: 
        !            57:     { ngx_string("real_ip_header"),
        !            58:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
        !            59:       ngx_http_realip,
        !            60:       NGX_HTTP_LOC_CONF_OFFSET,
        !            61:       0,
        !            62:       NULL },
        !            63: 
        !            64:     { ngx_string("real_ip_recursive"),
        !            65:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
        !            66:       ngx_conf_set_flag_slot,
        !            67:       NGX_HTTP_LOC_CONF_OFFSET,
        !            68:       offsetof(ngx_http_realip_loc_conf_t, recursive),
        !            69:       NULL },
        !            70: 
        !            71:       ngx_null_command
        !            72: };
        !            73: 
        !            74: 
        !            75: 
        !            76: static ngx_http_module_t  ngx_http_realip_module_ctx = {
        !            77:     NULL,                                  /* preconfiguration */
        !            78:     ngx_http_realip_init,                  /* postconfiguration */
        !            79: 
        !            80:     NULL,                                  /* create main configuration */
        !            81:     NULL,                                  /* init main configuration */
        !            82: 
        !            83:     NULL,                                  /* create server configuration */
        !            84:     NULL,                                  /* merge server configuration */
        !            85: 
        !            86:     ngx_http_realip_create_loc_conf,       /* create location configuration */
        !            87:     ngx_http_realip_merge_loc_conf         /* merge location configuration */
        !            88: };
        !            89: 
        !            90: 
        !            91: ngx_module_t  ngx_http_realip_module = {
        !            92:     NGX_MODULE_V1,
        !            93:     &ngx_http_realip_module_ctx,           /* module context */
        !            94:     ngx_http_realip_commands,              /* module directives */
        !            95:     NGX_HTTP_MODULE,                       /* module type */
        !            96:     NULL,                                  /* init master */
        !            97:     NULL,                                  /* init module */
        !            98:     NULL,                                  /* init process */
        !            99:     NULL,                                  /* init thread */
        !           100:     NULL,                                  /* exit thread */
        !           101:     NULL,                                  /* exit process */
        !           102:     NULL,                                  /* exit master */
        !           103:     NGX_MODULE_V1_PADDING
        !           104: };
        !           105: 
        !           106: 
        !           107: static ngx_int_t
        !           108: ngx_http_realip_handler(ngx_http_request_t *r)
        !           109: {
        !           110:     u_char                      *p;
        !           111:     size_t                       len;
        !           112:     ngx_str_t                   *value;
        !           113:     ngx_uint_t                   i, hash;
        !           114:     ngx_addr_t                   addr;
        !           115:     ngx_array_t                 *xfwd;
        !           116:     ngx_list_part_t             *part;
        !           117:     ngx_table_elt_t             *header;
        !           118:     ngx_connection_t            *c;
        !           119:     ngx_http_realip_ctx_t       *ctx;
        !           120:     ngx_http_realip_loc_conf_t  *rlcf;
        !           121: 
        !           122:     ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
        !           123: 
        !           124:     if (ctx) {
        !           125:         return NGX_DECLINED;
        !           126:     }
        !           127: 
        !           128:     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
        !           129: 
        !           130:     if (rlcf->from == NULL) {
        !           131:         return NGX_DECLINED;
        !           132:     }
        !           133: 
        !           134:     switch (rlcf->type) {
        !           135: 
        !           136:     case NGX_HTTP_REALIP_XREALIP:
        !           137: 
        !           138:         if (r->headers_in.x_real_ip == NULL) {
        !           139:             return NGX_DECLINED;
        !           140:         }
        !           141: 
        !           142:         value = &r->headers_in.x_real_ip->value;
        !           143:         xfwd = NULL;
        !           144: 
        !           145:         break;
        !           146: 
        !           147:     case NGX_HTTP_REALIP_XFWD:
        !           148: 
        !           149:         xfwd = &r->headers_in.x_forwarded_for;
        !           150: 
        !           151:         if (xfwd->elts == NULL) {
        !           152:             return NGX_DECLINED;
        !           153:         }
        !           154: 
        !           155:         value = NULL;
        !           156: 
        !           157:         break;
        !           158: 
        !           159:     default: /* NGX_HTTP_REALIP_HEADER */
        !           160: 
        !           161:         part = &r->headers_in.headers.part;
        !           162:         header = part->elts;
        !           163: 
        !           164:         hash = rlcf->hash;
        !           165:         len = rlcf->header.len;
        !           166:         p = rlcf->header.data;
        !           167: 
        !           168:         for (i = 0; /* void */ ; i++) {
        !           169: 
        !           170:             if (i >= part->nelts) {
        !           171:                 if (part->next == NULL) {
        !           172:                     break;
        !           173:                 }
        !           174: 
        !           175:                 part = part->next;
        !           176:                 header = part->elts;
        !           177:                 i = 0;
        !           178:             }
        !           179: 
        !           180:             if (hash == header[i].hash
        !           181:                 && len == header[i].key.len
        !           182:                 && ngx_strncmp(p, header[i].lowcase_key, len) == 0)
        !           183:             {
        !           184:                 value = &header[i].value;
        !           185:                 xfwd = NULL;
        !           186: 
        !           187:                 goto found;
        !           188:             }
        !           189:         }
        !           190: 
        !           191:         return NGX_DECLINED;
        !           192:     }
        !           193: 
        !           194: found:
        !           195: 
        !           196:     c = r->connection;
        !           197: 
        !           198:     addr.sockaddr = c->sockaddr;
        !           199:     addr.socklen = c->socklen;
        !           200:     /* addr.name = c->addr_text; */
        !           201: 
        !           202:     if (ngx_http_get_forwarded_addr(r, &addr, xfwd, value, rlcf->from,
        !           203:                                     rlcf->recursive)
        !           204:         != NGX_DECLINED)
        !           205:     {
        !           206:         return ngx_http_realip_set_addr(r, &addr);
        !           207:     }
        !           208: 
        !           209:     return NGX_DECLINED;
        !           210: }
        !           211: 
        !           212: 
        !           213: static ngx_int_t
        !           214: ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
        !           215: {
        !           216:     size_t                  len;
        !           217:     u_char                 *p;
        !           218:     u_char                  text[NGX_SOCKADDR_STRLEN];
        !           219:     ngx_connection_t       *c;
        !           220:     ngx_pool_cleanup_t     *cln;
        !           221:     ngx_http_realip_ctx_t  *ctx;
        !           222: 
        !           223:     cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
        !           224:     if (cln == NULL) {
        !           225:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           226:     }
        !           227: 
        !           228:     ctx = cln->data;
        !           229:     ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
        !           230: 
        !           231:     c = r->connection;
        !           232: 
        !           233:     len = ngx_sock_ntop(addr->sockaddr, text, NGX_SOCKADDR_STRLEN, 0);
        !           234:     if (len == 0) {
        !           235:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           236:     }
        !           237: 
        !           238:     p = ngx_pnalloc(c->pool, len);
        !           239:     if (p == NULL) {
        !           240:         return NGX_HTTP_INTERNAL_SERVER_ERROR;
        !           241:     }
        !           242: 
        !           243:     ngx_memcpy(p, text, len);
        !           244: 
        !           245:     cln->handler = ngx_http_realip_cleanup;
        !           246: 
        !           247:     ctx->connection = c;
        !           248:     ctx->sockaddr = c->sockaddr;
        !           249:     ctx->socklen = c->socklen;
        !           250:     ctx->addr_text = c->addr_text;
        !           251: 
        !           252:     c->sockaddr = addr->sockaddr;
        !           253:     c->socklen = addr->socklen;
        !           254:     c->addr_text.len = len;
        !           255:     c->addr_text.data = p;
        !           256: 
        !           257:     return NGX_DECLINED;
        !           258: }
        !           259: 
        !           260: 
        !           261: static void
        !           262: ngx_http_realip_cleanup(void *data)
        !           263: {
        !           264:     ngx_http_realip_ctx_t *ctx = data;
        !           265: 
        !           266:     ngx_connection_t  *c;
        !           267: 
        !           268:     c = ctx->connection;
        !           269: 
        !           270:     c->sockaddr = ctx->sockaddr;
        !           271:     c->socklen = ctx->socklen;
        !           272:     c->addr_text = ctx->addr_text;
        !           273: }
        !           274: 
        !           275: 
        !           276: static char *
        !           277: ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           278: {
        !           279:     ngx_http_realip_loc_conf_t *rlcf = conf;
        !           280: 
        !           281:     ngx_int_t                rc;
        !           282:     ngx_str_t               *value;
        !           283:     ngx_cidr_t              *cidr;
        !           284: 
        !           285:     value = cf->args->elts;
        !           286: 
        !           287:     if (rlcf->from == NULL) {
        !           288:         rlcf->from = ngx_array_create(cf->pool, 2,
        !           289:                                       sizeof(ngx_cidr_t));
        !           290:         if (rlcf->from == NULL) {
        !           291:             return NGX_CONF_ERROR;
        !           292:         }
        !           293:     }
        !           294: 
        !           295:     cidr = ngx_array_push(rlcf->from);
        !           296:     if (cidr == NULL) {
        !           297:         return NGX_CONF_ERROR;
        !           298:     }
        !           299: 
        !           300: #if (NGX_HAVE_UNIX_DOMAIN)
        !           301: 
        !           302:     if (ngx_strcmp(value[1].data, "unix:") == 0) {
        !           303:          cidr->family = AF_UNIX;
        !           304:          return NGX_CONF_OK;
        !           305:     }
        !           306: 
        !           307: #endif
        !           308: 
        !           309:     rc = ngx_ptocidr(&value[1], cidr);
        !           310: 
        !           311:     if (rc == NGX_ERROR) {
        !           312:         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
        !           313:                            &value[1]);
        !           314:         return NGX_CONF_ERROR;
        !           315:     }
        !           316: 
        !           317:     if (rc == NGX_DONE) {
        !           318:         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
        !           319:                            "low address bits of %V are meaningless", &value[1]);
        !           320:     }
        !           321: 
        !           322:     return NGX_CONF_OK;
        !           323: }
        !           324: 
        !           325: 
        !           326: static char *
        !           327: ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
        !           328: {
        !           329:     ngx_http_realip_loc_conf_t *rlcf = conf;
        !           330: 
        !           331:     ngx_str_t  *value;
        !           332: 
        !           333:     value = cf->args->elts;
        !           334: 
        !           335:     if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) {
        !           336:         rlcf->type = NGX_HTTP_REALIP_XREALIP;
        !           337:         return NGX_CONF_OK;
        !           338:     }
        !           339: 
        !           340:     if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) {
        !           341:         rlcf->type = NGX_HTTP_REALIP_XFWD;
        !           342:         return NGX_CONF_OK;
        !           343:     }
        !           344: 
        !           345:     rlcf->type = NGX_HTTP_REALIP_HEADER;
        !           346:     rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len);
        !           347:     rlcf->header = value[1];
        !           348: 
        !           349:     return NGX_CONF_OK;
        !           350: }
        !           351: 
        !           352: 
        !           353: static void *
        !           354: ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
        !           355: {
        !           356:     ngx_http_realip_loc_conf_t  *conf;
        !           357: 
        !           358:     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_realip_loc_conf_t));
        !           359:     if (conf == NULL) {
        !           360:         return NULL;
        !           361:     }
        !           362: 
        !           363:     /*
        !           364:      * set by ngx_pcalloc():
        !           365:      *
        !           366:      *     conf->from = NULL;
        !           367:      *     conf->hash = 0;
        !           368:      *     conf->header = { 0, NULL };
        !           369:      */
        !           370: 
        !           371:     conf->type = NGX_CONF_UNSET_UINT;
        !           372:     conf->recursive = NGX_CONF_UNSET;
        !           373: 
        !           374:     return conf;
        !           375: }
        !           376: 
        !           377: 
        !           378: static char *
        !           379: ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
        !           380: {
        !           381:     ngx_http_realip_loc_conf_t  *prev = parent;
        !           382:     ngx_http_realip_loc_conf_t  *conf = child;
        !           383: 
        !           384:     if (conf->from == NULL) {
        !           385:         conf->from = prev->from;
        !           386:     }
        !           387: 
        !           388:     ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
        !           389:     ngx_conf_merge_value(conf->recursive, prev->recursive, 0);
        !           390: 
        !           391:     if (conf->header.len == 0) {
        !           392:         conf->hash = prev->hash;
        !           393:         conf->header = prev->header;
        !           394:     }
        !           395: 
        !           396:     return NGX_CONF_OK;
        !           397: }
        !           398: 
        !           399: 
        !           400: static ngx_int_t
        !           401: ngx_http_realip_init(ngx_conf_t *cf)
        !           402: {
        !           403:     ngx_http_handler_pt        *h;
        !           404:     ngx_http_core_main_conf_t  *cmcf;
        !           405: 
        !           406:     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
        !           407: 
        !           408:     h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
        !           409:     if (h == NULL) {
        !           410:         return NGX_ERROR;
        !           411:     }
        !           412: 
        !           413:     *h = ngx_http_realip_handler;
        !           414: 
        !           415:     h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
        !           416:     if (h == NULL) {
        !           417:         return NGX_ERROR;
        !           418:     }
        !           419: 
        !           420:     *h = ngx_http_realip_handler;
        !           421: 
        !           422:     return NGX_OK;
        !           423: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>