May 012012
 

ISC에서 2012년 4월 초에 릴리즈된 버전에 문제가 있다라고 합니다. 5월 중순에 문제를 해결한 버전을 다시 릴리즈를 한다라고 합니다.

https://lists.isc.org/pipermail/bind-announce/2012-April/000772.html

관심이 있는 분야라서 소스를 확인해봤습니다. 패치가 나오면 제가 예상 했던 부분과 비교를 해봐야 할것 같네요.

 
[stone@localhost ~]$ diff -Nur bind-9.7.4-P1/lib/dns/resolver.c bind-9.7.5/lib/dns/resolver.c  
--- bind-9.7.4-P1/lib/dns/resolver.c    2011-06-09 08:15:43.000000000 +0900
+++ bind-9.7.5/lib/dns/resolver.c       2012-03-23 04:14:04.000000000 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
  * Copyright (C) 1999-2003  Internet Software Consortium.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: resolver.c,v 1.413.14.17 2011-06-08 23:15:43 each Exp $ */
+/* $Id$ */
 
 /*! \file */
 
@@ -208,6 +208,8 @@
        ISC_LIST(dns_validator_t)       validators;
        dns_db_t *                      cache;
        dns_adb_t *                     adb;
+       isc_boolean_t                   ns_ttl_ok;
+       isc_uint32_t                    ns_ttl;
 
        /*%
         * The number of events we're waiting for.
@@ -444,7 +446,7 @@
                                      dns_rdataset_t *ardataset,
                                      isc_result_t *eresultp);
 static void validated(isc_task_t *task, isc_event_t *event);
-static void maybe_destroy(fetchctx_t *fctx);
+static isc_boolean_t maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked);
 static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
                    isc_result_t reason, badnstype_t badtype);
 
@@ -737,8 +739,11 @@
        INSIST(query->tcpsocket == NULL);
 
        query->fctx->nqueries--;
-       if (SHUTTINGDOWN(query->fctx))
-               maybe_destroy(query->fctx);     /* Locks bucket. */
+       if (SHUTTINGDOWN(query->fctx)) {
+               dns_resolver_t *res = query->fctx->res;
+               if (maybe_destroy(query->fctx, ISC_FALSE))
+                       empty_bucket(res);
+       }
        query->magic = 0;
        isc_mem_put(query->mctx, query, sizeof(*query));
        *queryp = NULL;
@@ -1553,9 +1558,11 @@
                dns_dispatch_detach(&query->dispatch);
 
  cleanup_query:
-       query->magic = 0;
-       isc_mem_put(res->buckets[fctx->bucketnum].mctx,
-                   query, sizeof(*query));
+       if (query->connects == 0) {
+               query->magic = 0;
+               isc_mem_put(res->buckets[fctx->bucketnum].mctx,
+                           query, sizeof(*query));
+       }
 
  stop_idle_timer:
        RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);
@@ -1673,6 +1680,7 @@
        dns_compress_t cctx;
        isc_boolean_t cleanup_cctx = ISC_FALSE;
        isc_boolean_t secure_domain;
+       isc_boolean_t connecting = ISC_FALSE;
 
        fctx = query->fctx;
        QTRACE("send");
@@ -1963,6 +1971,7 @@
                                                    query);
                        if (result != ISC_R_SUCCESS)
                                goto cleanup_message;
+                       connecting = ISC_TRUE;
                        query->connects++;
                }
        }
@@ -1974,8 +1983,19 @@
         */
        result = isc_socket_sendto(socket, &r, task, resquery_senddone,
                                   query, address, NULL);
-       if (result != ISC_R_SUCCESS)
+       if (result != ISC_R_SUCCESS) {
+               if (connecting) {
+                       /*
+                        * This query is still connecting.
+                        * Mark it as canceled so that it will just be
+                        * cleaned up when the connected event is received.
+                        * Keep fctx around until the event is processed.
+                        */
+                       query->fctx->nqueries++;
+                       query->attributes |= RESQUERY_ATTR_CANCELED;
+               }
                goto cleanup_message;
+       }
 
        query->sends++;
 
@@ -2137,6 +2157,7 @@
        isc_boolean_t want_try = ISC_FALSE;
        isc_boolean_t want_done = ISC_FALSE;
        isc_boolean_t bucket_empty = ISC_FALSE;
+       isc_boolean_t destroy = ISC_FALSE;
        unsigned int bucketnum;
 
        find = event->ev_sender;
@@ -2148,6 +2169,9 @@
 
        FCTXTRACE("finddone");
 
+       bucketnum = fctx->bucketnum;
+       LOCK(&res->buckets[bucketnum].lock);
+
        INSIST(fctx->pending > 0);
        fctx->pending--;
 
@@ -2172,17 +2196,17 @@
                }
        } else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&
                   fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {
-               bucketnum = fctx->bucketnum;
-               LOCK(&res->buckets[bucketnum].lock);
                /*
                 * Note that we had to wait until we had the lock before
                 * looking at fctx->references.
                 */
                if (fctx->references == 0)
-                       bucket_empty = fctx_destroy(fctx);
-               UNLOCK(&res->buckets[bucketnum].lock);
+                       destroy = ISC_TRUE;
        }
+       UNLOCK(&res->buckets[bucketnum].lock);
 
+       if (destroy)
+               bucket_empty = fctx_destroy(fctx);
        isc_event_free(&event);
        dns_adb_destroyfind(&find);
 
@@ -3476,6 +3500,20 @@
        return (ISC_R_SUCCESS);
 }
 
+static inline void
+log_ns_ttl(fetchctx_t *fctx, const char *where) {
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char domainbuf[DNS_NAME_FORMATSIZE];
+
+       dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+       dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
+       isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+                     DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
+                     "log_ns_ttl: fctx %p: %s: %s (in '%s'?): %u %u",
+                     fctx, where, namebuf, domainbuf,
+                     fctx->ns_ttl_ok, fctx->ns_ttl);
+}
+
 static isc_result_t
 fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,
            dns_name_t *domain, dns_rdataset_t *nameservers,
@@ -3569,6 +3607,8 @@
        fctx->timeout = ISC_FALSE;
        fctx->addrinfo = NULL;
        fctx->client = NULL;
+       fctx->ns_ttl = 0;
+       fctx->ns_ttl_ok = ISC_FALSE;
 
        dns_name_init(&fctx->nsname, NULL);
        fctx->nsfetch = NULL;
@@ -3618,6 +3658,8 @@
                                dns_rdataset_disassociate(&fctx->nameservers);
                                goto cleanup_name;
                        }
+                       fctx->ns_ttl = fctx->nameservers.ttl;
+                       fctx->ns_ttl_ok = ISC_TRUE;
                } else {
                        /*
                         * We're in forward-only mode.  Set the query domain.
@@ -3635,8 +3677,12 @@
                if (result != ISC_R_SUCCESS)
                        goto cleanup_name;
                dns_rdataset_clone(nameservers, &fctx->nameservers);
+               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl_ok = ISC_TRUE;
        }
 
+       log_ns_ttl(fctx, "fctx_create");
+
        INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));
 
        fctx->qmessage = NULL;
@@ -3929,14 +3975,16 @@
 
 /*
  * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has
- * no references and is no longer waiting for any events).  If this
- * was the last fctx in the resolver, destroy the resolver.
+ * no references and is no longer waiting for any events).
  *
  * Requires:
  *      '*fctx' is shutting down.
+ *
+ * Returns:
+ *     true if the resolver is exiting and this is the last fctx in the bucket.
  */
-static void
-maybe_destroy(fetchctx_t *fctx) {
+static isc_boolean_t
+maybe_destroy(fetchctx_t *fctx, isc_boolean_t locked) {
        unsigned int bucketnum;
        isc_boolean_t bucket_empty = ISC_FALSE;
        dns_resolver_t *res = fctx->res;
@@ -3944,8 +3992,11 @@
 
        REQUIRE(SHUTTINGDOWN(fctx));
 
+       bucketnum = fctx->bucketnum;
+       if (!locked)
+               LOCK(&res->buckets[bucketnum].lock);
        if (fctx->pending != 0 || fctx->nqueries != 0)
-               return;
+               goto unlock;
 
        for (validator = ISC_LIST_HEAD(fctx->validators);
             validator != NULL; validator = next_validator) {
@@ -3953,14 +4004,12 @@
                dns_validator_cancel(validator);
        }
 
-       bucketnum = fctx->bucketnum;
-       LOCK(&res->buckets[bucketnum].lock);
        if (fctx->references == 0 && ISC_LIST_EMPTY(fctx->validators))
                bucket_empty = fctx_destroy(fctx);
-       UNLOCK(&res->buckets[bucketnum].lock);
-
-       if (bucket_empty)
-               empty_bucket(res);
+ unlock:
+       if (!locked)
+               UNLOCK(&res->buckets[bucketnum].lock);
+       return (bucket_empty);
 }
 
 /*
@@ -3968,31 +4017,33 @@
  */
 static void
 validated(isc_task_t *task, isc_event_t *event) {
-       isc_result_t result = ISC_R_SUCCESS;
-       isc_result_t eresult = ISC_R_SUCCESS;
-       isc_stdtime_t now;
-       fetchctx_t *fctx;
-       dns_validatorevent_t *vevent;
-       dns_fetchevent_t *hevent;
-       dns_rdataset_t *ardataset = NULL;
-       dns_rdataset_t *asigrdataset = NULL;
+       dns_adbaddrinfo_t *addrinfo;
        dns_dbnode_t *node = NULL;
-       isc_boolean_t negative;
-       isc_boolean_t chaining;
-       isc_boolean_t sentresponse;
-       isc_uint32_t ttl;
        dns_dbnode_t *nsnode = NULL;
+       dns_fetchevent_t *hevent;
        dns_name_t *name;
+       dns_rdataset_t *ardataset = NULL;
+       dns_rdataset_t *asigrdataset = NULL;
        dns_rdataset_t *rdataset;
        dns_rdataset_t *sigrdataset;
+       dns_resolver_t *res;
        dns_valarg_t *valarg;
-       dns_adbaddrinfo_t *addrinfo;
+       dns_validatorevent_t *vevent;
+       fetchctx_t *fctx;
+       isc_boolean_t chaining;
+       isc_boolean_t negative;
+       isc_boolean_t sentresponse;
+       isc_result_t eresult = ISC_R_SUCCESS;
+       isc_result_t result = ISC_R_SUCCESS;
+       isc_stdtime_t now;
+       isc_uint32_t ttl;
 
        UNUSED(task); /* for now */
 
        REQUIRE(event->ev_type == DNS_EVENT_VALIDATORDONE);
        valarg = event->ev_arg;
        fctx = valarg->fctx;
+       res = fctx->res;
        addrinfo = valarg->addrinfo;
        REQUIRE(VALID_FCTX(fctx));
        REQUIRE(!ISC_LIST_EMPTY(fctx->validators));
@@ -4002,6 +4053,8 @@
 
        FCTXTRACE("received validation completion event");
 
+       LOCK(&res->buckets[fctx->bucketnum].lock);
+
        ISC_LIST_UNLINK(fctx->validators, vevent->validator, link);
        fctx->validator = NULL;
 
@@ -4010,7 +4063,7 @@
         * destroy the fctx if necessary.
         */
        dns_validator_destroy(&vevent->validator);
-       isc_mem_put(fctx->res->buckets[fctx->bucketnum].mctx,
+       isc_mem_put(res->buckets[fctx->bucketnum].mctx,
                    valarg, sizeof(*valarg));
 
        negative = ISC_TF(vevent->rdataset == NULL);
@@ -4023,12 +4076,15 @@
         * so, destroy the fctx.
         */
        if (SHUTTINGDOWN(fctx) && !sentresponse) {
-               maybe_destroy(fctx);    /* Locks bucket. */
+               isc_uint32_t bucketnum = fctx->bucketnum;
+               isc_boolean_t bucket_empty;
+               bucket_empty = maybe_destroy(fctx, ISC_TRUE);
+               UNLOCK(&res->buckets[bucketnum].lock);
+               if (bucket_empty)
+                       empty_bucket(res);
                goto cleanup_event;
        }
 
-       LOCK(&fctx->res->buckets[fctx->bucketnum].lock);
-
        isc_stdtime_get(&now);
 
        /*
@@ -4074,7 +4130,7 @@
 
        if (vevent->result != ISC_R_SUCCESS) {
                FCTXTRACE("validation failed");
-               inc_stats(fctx->res, dns_resstatscounter_valfail);
+               inc_stats(res, dns_resstatscounter_valfail);
                fctx->valfail++;
                fctx->vresult = vevent->result;
                if (fctx->vresult != DNS_R_BROKENCHAIN) {
@@ -4123,7 +4179,7 @@
                result = fctx->vresult;
                add_bad(fctx, addrinfo, result, badns_validation);
                isc_event_free(&event);
-               UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+               UNLOCK(&res->buckets[fctx->bucketnum].lock);
                INSIST(fctx->validator == NULL);
                fctx->validator = ISC_LIST_HEAD(fctx->validators);
                if (fctx->validator != NULL)
@@ -4142,8 +4198,7 @@
                             fctx->type == dns_rdatatype_dlv ||
                             fctx->type == dns_rdatatype_ds) &&
                             tresult == ISC_R_SUCCESS)
-                               dns_resolver_addbadcache(fctx->res,
-                                                        &fctx->name,
+                               dns_resolver_addbadcache(res, &fctx->name,
                                                         fctx->type, &expire);
                        fctx_done(fctx, result, __LINE__); /* Locks bucket. */
                } else
@@ -4156,7 +4211,7 @@
                dns_rdatatype_t covers;
                FCTXTRACE("nonexistence validation OK");
 
-               inc_stats(fctx->res, dns_resstatscounter_valnegsuccess);
+               inc_stats(res, dns_resstatscounter_valnegsuccess);
 
                if (fctx->rmessage->rcode == dns_rcode_nxdomain)
                        covers = dns_rdatatype_any;
@@ -4173,10 +4228,9 @@
                 * to zero to facilitate locating the containing zone of
                 * a arbitrary zone.
                 */
-               ttl = fctx->res->view->maxncachettl;
+               ttl = res->view->maxncachettl;
                if (fctx->type == dns_rdatatype_soa &&
-                   covers == dns_rdatatype_any &&
-                   fctx->res->zero_no_soa_ttl)
+                   covers == dns_rdatatype_any && res->zero_no_soa_ttl)
                        ttl = 0;
 
                result = ncache_adderesult(fctx->rmessage, fctx->cache, node,
@@ -4186,7 +4240,7 @@
                        goto noanswer_response;
                goto answer_response;
        } else
-               inc_stats(fctx->res, dns_resstatscounter_valsuccess);
+               inc_stats(res, dns_resstatscounter_valsuccess);
 
        FCTXTRACE("validation OK");
 
@@ -4234,14 +4288,17 @@
        }
 
        if (sentresponse) {
+               isc_boolean_t bucket_empty = ISC_FALSE;
                /*
                 * If we only deferred the destroy because we wanted to cache
                 * the data, destroy now.
                 */
                dns_db_detachnode(fctx->cache, &node);
-               UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
                if (SHUTTINGDOWN(fctx))
-                       maybe_destroy(fctx);    /* Locks bucket. */
+                       bucket_empty = maybe_destroy(fctx, ISC_TRUE);
+               UNLOCK(&res->buckets[fctx->bucketnum].lock);
+               if (bucket_empty)
+                       empty_bucket(res);
                goto cleanup_event;
        }
 
@@ -4256,7 +4313,7 @@
                 * be validated.
                 */
                dns_db_detachnode(fctx->cache, &node);
-               UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
+               UNLOCK(&res->buckets[fctx->bucketnum].lock);
                dns_validator_send(ISC_LIST_HEAD(fctx->validators));
                goto cleanup_event;
        }
@@ -4331,8 +4388,7 @@
        if (node != NULL)
                dns_db_detachnode(fctx->cache, &node);
 
-       UNLOCK(&fctx->res->buckets[fctx->bucketnum].lock);
-
+       UNLOCK(&res->buckets[fctx->bucketnum].lock);
        fctx_done(fctx, result, __LINE__); /* Locks bucket. */
 
  cleanup_event:
@@ -5303,6 +5359,26 @@
        return (ISC_TRUE);
 }
 
+static void
+trim_ns_ttl(fetchctx_t *fctx, dns_name_t *name, dns_rdataset_t *rdataset) {
+       char ns_namebuf[DNS_NAME_FORMATSIZE];
+       char namebuf[DNS_NAME_FORMATSIZE];
+       char tbuf[DNS_RDATATYPE_FORMATSIZE];
+
+       if (fctx->ns_ttl_ok && rdataset->ttl > fctx->ns_ttl) {
+               dns_name_format(name, ns_namebuf, sizeof(ns_namebuf));
+               dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
+               dns_rdatatype_format(fctx->type, tbuf, sizeof(tbuf));
+
+               isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+                             DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(10),
+                             "fctx %p: trimming ttl of %s/NS for %s/%s: "
+                             "%u -> %u", fctx, ns_namebuf, namebuf, tbuf,
+                             rdataset->ttl, fctx->ns_ttl);
+               rdataset->ttl = fctx->ns_ttl;
+       }
+}
+
 /*
  * Handle a no-answer response (NXDOMAIN, NXRRSET, or referral).
  * If look_in_options has LOOK_FOR_NS_IN_ANSWER then we look in the answer
@@ -5473,6 +5549,9 @@
                                        if (aa)
                                                rdataset->trust =
                                                    dns_trust_authauthority;
+                                       else if (ISFORWARDER(fctx->addrinfo))
+                                               rdataset->trust =
+                                                       dns_trust_answer;
                                        else
                                                rdataset->trust =
                                                        dns_trust_additional;
@@ -5486,6 +5565,12 @@
                        return (result);
        }
 
+       log_ns_ttl(fctx, "noanswer_response");
+
+       if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
+           !dns_name_equal(ns_name, dns_rootname))
+               trim_ns_ttl(fctx, ns_name, ns_rdataset);
+
        /*
         * A negative response has a SOA record (Type 2)
         * and a optional NS RRset (Type 1) or it has neither
@@ -5526,6 +5611,9 @@
                                        if (aa)
                                                rdataset->trust =
                                                    dns_trust_authauthority;
+                                       else if (ISFORWARDER(fctx->addrinfo))
+                                               rdataset->trust =
+                                                       dns_trust_answer;
                                        else
                                                rdataset->trust =
                                                        dns_trust_additional;
@@ -5567,6 +5655,9 @@
                                        if (aa)
                                                rdataset->trust =
                                                    dns_trust_authauthority;
+                                       else if (ISFORWARDER(fctx->addrinfo))
+                                               rdataset->trust =
+                                                       dns_trust_answer;
                                        else
                                                rdataset->trust =
                                                        dns_trust_additional;
@@ -5698,6 +5789,8 @@
                if (result != ISC_R_SUCCESS)
                        return (result);
                fctx->attributes |= FCTX_ATTR_WANTCACHE;
+               fctx->ns_ttl_ok = ISC_FALSE;
+               log_ns_ttl(fctx, "DELEGATION");
                return (DNS_R_DELEGATION);
        }
 
@@ -5718,8 +5811,8 @@
 answer_response(fetchctx_t *fctx) {
        isc_result_t result;
        dns_message_t *message;
-       dns_name_t *name, *qname, tname;
-       dns_rdataset_t *rdataset;
+       dns_name_t *name, *qname, tname, *ns_name;
+       dns_rdataset_t *rdataset, *ns_rdataset;
        isc_boolean_t done, external, chaining, aa, found, want_chaining;
        isc_boolean_t have_answer, found_cname, found_type, wanted_chaining;
        unsigned int aflag;
@@ -6119,6 +6212,8 @@
         * in this section, and we expect that it is not external.
         */
        done = ISC_FALSE;
+       ns_name = NULL;
+       ns_rdataset = NULL;
        result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);
        while (!done && result == ISC_R_SUCCESS) {
                name = NULL;
@@ -6146,6 +6241,10 @@
                                                rdataset->trust =
                                                    dns_trust_additional;
 
+                                       if (rdataset->type == dns_rdatatype_ns) {
+                                               ns_name = name;
+                                               ns_rdataset = rdataset;
+                                       }
                                        /*
                                         * Mark any additional data related
                                         * to this rdataset.
@@ -6163,6 +6262,12 @@
        if (result == ISC_R_NOMORE)
                result = ISC_R_SUCCESS;
 
+       log_ns_ttl(fctx, "answer_response");
+
+       if (ns_rdataset != NULL && dns_name_equal(&fctx->domain, ns_name) &&
+           !dns_name_equal(ns_name, dns_rootname))
+               trim_ns_ttl(fctx, ns_name, ns_rdataset);
+
        return (result);
 }
 
@@ -6234,6 +6339,9 @@
                if (dns_rdataset_isassociated(&fctx->nameservers))
                        dns_rdataset_disassociate(&fctx->nameservers);
                dns_rdataset_clone(fevent->rdataset, &fctx->nameservers);
+               fctx->ns_ttl = fctx->nameservers.ttl;
+               fctx->ns_ttl_ok = ISC_TRUE;
+               log_ns_ttl(fctx, "resume_dslookup");
                dns_name_free(&fctx->domain,
                              fctx->res->buckets[bucketnum].mctx);
                dns_name_init(&fctx->domain, NULL);
@@ -7167,6 +7275,8 @@
                                fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
                                return;
                        }
+                       fctx->ns_ttl = fctx->nameservers.ttl;
+                       fctx->ns_ttl_ok = ISC_TRUE;
                        fctx_cancelqueries(fctx, ISC_TRUE);
                        fctx_cleanupfinds(fctx);
                        fctx_cleanupaltfinds(fctx);
Print Friendly
Apr 242012
 

HTTP 헤더를 분석하다 보면 브라우저 정보 혹은 사용자 정보를 쉽게 확인하는 방법중에 하나로 User-Agent 헤더를 분석하는 경우가 많다.

생각보다 많은 정보를 가지고 있습니다. 참고할만한 사이트가 있어서 공유합니다.

http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx

다른 브라우저도 비슷한 구조를 가지고 있으면, MS의 Internet Explorer 운영 환경을 파악하는데 도움이 된다. 특히 아래와 같이 OS정보는 바로 응용이 가능합니다.

그리고 추가적으로 User-Agent 정보만 모아둔 사이트도 있다.
사이트에 보면 Chrome(http://www.useragentstring.com/pages/Chrome/) 혹은 Safari(http://www.useragentstring.com/pages/Safari/)에 대한 정보도 얻을수 있다.

http://www.useragentstring.com/pages/useragentstring.php

프로그램으로 웹클라이언트를 구현할때에도 해당 값들을 이용해서 신규로 생성하거나, 흉내를 낼수 있다.

Print Friendly
Apr 232012
 

예전에 만들었던 perl 프로그램을 실행했더니 아래와 같은 오류가 발생을 했습니다.
아마도 시스템에 기존에 패키지로 설치되었던 perl module이 upgrade가 되면서 발생된 이슈입니다.

관련된 모듈은 패키지로 설치되지 않고, CPAN Module을 통해서 설치된 모듈이라서 아래와 같은 현상이 발견이 되었습니다.

[root@localhost message]# perl xxx.pl
File::Temp version 0.18 required--this is only version 0.16 at /usr/lib/perl5/site_perl/5.8.8/MIME/Tools.pm line 14.
BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.8.8/MIME/Tools.pm line 14.
Compilation failed in require at /usr/lib/perl5/site_perl/5.8.8/MIME/Parser.pm line 140.
BEGIN failed--compilation aborted at /usr/lib/perl5/site_perl/5.8.8/MIME/Parser.pm line 140.
Compilation failed in require at xxx.pl line 6.
BEGIN failed--compilation aborted at xxx.pl line 6.

이런 경우에는 CPAN 모듈을 어떻게 업데이트를 할까 고민을 하다가 그냥 기존 설치된 모듈을 다시 설치를 하니 업데이트가 되더군요.
아래아 같이 기존의 CPAN 모듈 업데이트 방법으로 설치를 하면 됩니다.

[root@localhost message]# perl -MCPAN -e shell
Terminal does not support AddHistory.

cpan shell -- CPAN exploration and modules installation (v1.7602)
ReadLine support available (try 'install Bundle::CPAN')

cpan> install File::Temp
Print Friendly
Apr 192012
 

Windows Vista부터 윈도우 사이드바를 통해서 가젯(Gadget)을 지원하고 있습니다.
특히 대형 화면 혹은 와이드 화면을 사용할 경우에 편리합니다.

이러한 가젯을 만들어서 판매를 하는 곳도 있지만, 프로그램을 했던 사람들은 간단히 만들어서 사용을 할수 있습니다.
아래는 운영체제에 기본으로 포함되어 있는 가젯들의 위치이며, 확인을 해보면 xml, html, css, javascript로 이루어져 있는 것을 확인할 수 있습니다.

다른 가젯 프로그램도 인터넷에서 다운을 받으면 확장자가 gadget 이지만, 실제적으로 zip으로 압축이 되어 있는 형태입니다.
그래서 확장자를 변경후에 압축을 풀어서 내부 내용을 참고해서 개발이 가능합니다.

개발에 대한 개념은 아래의 사이트를 한번만 읽어보면 쉽게 이해가 됩니다.

http://msdn.microsoft.com/ko-kr/magazine/cc163370.aspx

참고로 웹에서 다운로드 서비스를 제공하고자 한다면 .gadget에 대해서 아래와 같은 형식의 MIME을 제공해야만 윈도우 운영체제에서 인식이 됩니다.

application/x-windows-gadget

Print Friendly
Apr 182012
 

예전부터 네트워크 프로그램을 많이 작성을 하면서 pcap 라이브러리를 이용해서 패킷캡쳐를 했었다.

http://luca.ntop.org/Ring.pdf

하지만 우연한 기회에 위의 논문에서 PF_RING이라는 방식으로 패킷을 캡쳐하면 패킷 캡쳐 효율이 보다 좋다는 것을 알게 되었다. 대부분 응용프로그램을 감시하는 프로그램에서는 기존의 방식으로도 충분하겠지만, 100M 이상의 네트워크를 처리하거나, 네트워크에서 모니터링을 목적으로 만든 장비에서는 중요한 항목이 될수 있으므로 관심을 가지게 되었다.
그래서 공개된 소스로 원리를 파악하고 기존의 프로그램을 업데이트의 필요성을 느끼게 되었다.

일단 아래의 사이트에서 PF_RING 커널 모듈을 따라서 설치하면 쉽게 설치를 할수 있다.

http://www.ntop.org/get-started/download/

kernel-devel 패키지가 설치가 되어 있는 경우라면 쉽게 컴파일을 해서 pf_ring.ko 파일 만들기가 되므로, insmod 명령어로 커널에 모듈로 올리면 된다.

[root@localhost PF_RING]# lsmod |grep pf_ring
pf_ring               365711  0

그리고 SVN 서버에서 usermode 프로그램 예제도 같이 들어가 있어서 소스도 확인을 할수 있고, 또한 샘플 프로그램도 확인이 가능하다. 그리고 pf_ring 을 사용하는 tcpdump 프로그램도 들어가 있는 것을 확인할 수 있다.

[root@localhost examples]# ./pcount
Capturing from eth0
=========================
Absolute Stats: [48 pkts rcvd][0 pkts dropped]
Total Pkts=48/Dropped=0.0 %
48 pkts [49.7 pkt/sec] - 2880 bytes [0.02 Mbit/sec]
=========================
=========================
Absolute Stats: [108 pkts rcvd][0 pkts dropped]
Total Pkts=108/Dropped=0.0 %
108 pkts [54.9 pkt/sec] - 6716 bytes [0.03 Mbit/sec]
=========================
Actual Stats: 108 pkts [1000.1 ms][107.98 pkt/sec]
=========================
=========================
Absolute Stats: [158 pkts rcvd][0 pkts dropped]
Total Pkts=158/Dropped=0.0 %
158 pkts [53.3 pkt/sec] - 10032 bytes [0.03 Mbit/sec]
=========================
Actual Stats: 50 pkts [1000.1 ms][50.00 pkt/sec]
=========================

소스를 확인해보면 기존의 라이브러리 대신에 소스에 포함되어 있는 pfring과 pcap 라이브러리를 사용해서 컴파일을 하면 된다.

[root@localhost userland]# ldd examples/pcount
        linux-vdso.so.1 =>  (0x00007fffaf179000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003664800000)
        libc.so.6 => /lib64/libc.so.6 (0x0000003664000000)
        /lib64/ld-linux-x86-64.so.2 (0x0000003663800000)
[root@localhost userland]# ls -al libpcap/libpcap.a
-rw-r--r-- 1 root root 401912 2012-04-18 18:19 libpcap/libpcap.a
[root@localhost userland]# ls -al lib/libpfring.a
-rw-r--r-- 1 root root 172836 2012-04-18 18:18 lib/libpfring.a

[root@localhost userland]# cd examples/
[root@localhost examples]# touch pcount.c
[root@localhost examples]# make
gcc  -O2 -Wall -I../../kernel -I../../kernel/plugins -I../lib -I../libpcap-1.1.1-ring  -D HAVE_ZERO -O2  -c pcount.c -o pcount.o
gcc  -O2 -Wall -I../../kernel -I../../kernel/plugins -I../lib -I../libpcap-1.1.1-ring  -D HAVE_ZERO -O2  pcount.o ../libpcap-1.1.1-ring/libpcap.a   ../lib/libpfring.a  -lpthread  -L../libpcap -lpcap   -o pcount
Print Friendly
Plugin from the creators of Brindes :: More at Plulz Wordpress Plugins